From 347e2b1dd4af4799302eb638a053a7083422a20f Mon Sep 17 00:00:00 2001 From: Claus Holbech Date: Wed, 27 Nov 2024 17:35:30 +0100 Subject: [PATCH] Refactor(eos_designs): Use python classes built from schemas for inputs (#4603) --- .gitattributes | 2 + .github/yamllintrc | 1 + .pre-commit-config.yaml | 4 +- .sonarcloud.properties | 6 +- .../arista/avd/docs/release-notes/5.x.x.md | 28 +- .../intended/structured_configs/LEAF1A.yml | 384 +- .../intended/structured_configs/LEAF1B.yml | 384 +- .../intended/structured_configs/LEAF2A.yml | 1920 +- .../intended/structured_configs/LEAF3A.yml | 768 +- .../intended/structured_configs/LEAF3B.yml | 768 +- .../intended/structured_configs/LEAF3C.yml | 768 +- .../intended/structured_configs/LEAF3D.yml | 768 +- .../intended/structured_configs/LEAF3E.yml | 768 +- .../structured_configs/inet-cloud.yml | 2 +- .../intended/structured_configs/pf1.yml | 26 +- .../intended/structured_configs/pf2.yml | 26 +- .../structured_configs/site1-wan1.yml | 20 +- .../structured_configs/site1-wan2.yml | 20 +- .../structured_configs/site2-wan1.yml | 2 +- .../structured_configs/site2-wan2.yml | 26 +- .../structured_configs/site3-wan1.yml | 20 +- .../intended/structured_configs/pe1.yml | 2 +- .../intended/structured_configs/pe2.yml | 2 +- .../intended/structured_configs/pe3.yml | 2 +- .../structured_configs/SITE1-LER1.yml | 2 +- .../structured_configs/SITE1-LER2.yml | 2 +- .../structured_configs/SITE2-LER1.yml | 4 +- .../structured_configs/DC1-POD1-L2LEAF1A.yml | 2 +- .../structured_configs/DC1-POD1-L2LEAF2A.yml | 2 +- .../structured_configs/DC1-POD1-L2LEAF2B.yml | 2 +- .../structured_configs/DC1-POD1-LEAF1A.yml | 2 +- .../structured_configs/DC1-POD1-LEAF2B.yml | 2 +- .../structured_configs/DC1-POD1-SPINE1.yml | 2 +- .../structured_configs/DC1-POD1-SPINE2.yml | 2 +- .../structured_configs/DC1-POD2-LEAF1A.yml | 2 +- .../structured_configs/DC1-POD2-SPINE1.yml | 2 +- .../structured_configs/DC1-POD2-SPINE2.yml | 2 +- .../intended/structured_configs/DC1-RS1.yml | 2 +- .../intended/structured_configs/DC1-RS2.yml | 2 +- .../structured_configs/DC1-SUPER-SPINE1.yml | 2 +- .../structured_configs/DC1-SUPER-SPINE2.yml | 2 +- .../structured_configs/DC1.POD1.LEAF2A.yml | 2 +- .../structured_configs/DC2-POD1-L2LEAF1A.yml | 2 +- .../structured_configs/DC2-POD1-L2LEAF2A.yml | 2 +- .../structured_configs/DC2-POD1-LEAF1A.yml | 2 +- .../structured_configs/DC2-POD1-LEAF2A.yml | 2 +- .../structured_configs/DC2-POD1-SPINE1.yml | 2 +- .../structured_configs/DC2-POD1-SPINE2.yml | 2 +- .../intended/structured_configs/DC2-RS1.yml | 2 +- .../intended/structured_configs/DC2-RS2.yml | 2 +- .../structured_configs/DC2-SUPER-SPINE1.yml | 2 +- .../structured_configs/DC2-SUPER-SPINE2.yml | 2 +- .../intended/configs/host1.cfg | 6 + .../intended/structured_configs/host1.yml | 7 + .../intended/configs/core-1-isis-sr-ldp.cfg | 2 + .../intended/configs/core-2-ospf-ldp.cfg | 2 + .../custom-structured-configuration.cfg | 5 +- .../structured_configs/7010TX-LEAF1.yml | 1 - .../structured_configs/7010TX-LEAF2.yml | 1 - .../intended/structured_configs/DC1-BL1A.yml | 40 +- .../intended/structured_configs/DC1-BL1B.yml | 42 +- .../intended/structured_configs/DC1-BL2A.yml | 14 +- .../intended/structured_configs/DC1-BL2B.yml | 14 +- .../structured_configs/DC1-LEAF1A.yml | 2 +- .../structured_configs/DC1-LEAF2A.yml | 16 +- .../structured_configs/DC1-LEAF2B.yml | 14 +- .../intended/structured_configs/DC1-SVC3A.yml | 12 +- .../intended/structured_configs/DC1-SVC3B.yml | 12 +- .../DC1_UNDEPLOYED_LEAF1A.yml | 12 +- .../DC1_UNDEPLOYED_LEAF1B.yml | 12 +- .../intended/structured_configs/DUP-LEAF1.yml | 1 - .../intended/structured_configs/DUP-LEAF2.yml | 1 - .../structured_configs/MLAG-ISIS-L3LEAF1A.yml | 1 - .../structured_configs/MLAG-ISIS-L3LEAF1B.yml | 1 - .../structured_configs/MLAG_IPV6_L3LEAF1A.yml | 1 - .../structured_configs/MLAG_IPV6_L3LEAF1B.yml | 1 - .../MLAG_ODD_ID_L3LEAF1A.yml | 1 - .../MLAG_ODD_ID_L3LEAF1B.yml | 1 - .../MLAG_SAME_SUBNET_L3LEAF1A.yml | 1 - .../MLAG_SAME_SUBNET_L3LEAF1B.yml | 1 - .../MLAG_SAME_SUBNET_L3LEAF2A.yml | 1 - .../MLAG_SAME_SUBNET_L3LEAF2B.yml | 1 - .../OVERLAY_ROUTING_PROTOCOL_CVX_SERVER1.yml | 1 - .../OVERLAY_ROUTING_PROTOCOL_CVX_SERVER2.yml | 1 - .../OVERRIDE_VTEP_L3LEAF1A.yml | 1 - .../OVERRIDE_VTEP_L3LEAF1B.yml | 1 - .../structured_configs/SVI_PROFILE_NODE_1.yml | 2 +- .../structured_configs/SVI_PROFILE_NODE_2.yml | 2 +- .../bgp-from-network-services-1.yml | 3 +- .../bgp-from-network-services-2.yml | 1 - .../structured_configs/core-1-isis-sr-ldp.yml | 2 + .../structured_configs/core-2-ospf-ldp.yml | 2 + .../custom-structured-configuration.yml | 8 +- ...der-custom-control-plane-policy-edge-1.yml | 8 +- ...der-custom-control-plane-policy-edge-2.yml | 8 +- ...stom-control-plane-policy-pathfinder-1.yml | 8 +- .../structured_configs/cv-pathfinder-edge.yml | 20 +- .../cv-pathfinder-edge1.yml | 66 +- .../cv-pathfinder-edge2A.yml | 8 +- .../cv-pathfinder-edge2B.yml | 8 +- .../cv-pathfinder-edge3A.yml | 8 +- .../cv-pathfinder-edge3B.yml | 8 +- .../cv-pathfinder-edge4A.yml | 8 +- .../cv-pathfinder-edge4B.yml | 8 +- .../cv-pathfinder-pathfinder.yml | 8 +- .../cv-pathfinder-pathfinder1.yml | 8 +- .../cv-pathfinder-pathfinder2.yml | 8 +- .../cv-pathfinder-transit1A.yml | 8 +- .../cv-pathfinder-transit1B.yml | 8 +- .../evpn_l2_multi_domain.yml | 1 - .../evpn_services_l2_only_false.yml | 14 +- .../ignore-custom-keys-in-data-models.yml | 4 +- .../intended/structured_configs/ipv4-acls.yml | 60 +- .../mgmt_interface_ipv6.yml | 2 - .../structured_configs/no_mgmt_gateway.yml | 1 - .../structured_configs/ntp-settings-1.yml | 1 - .../structured_configs/platform_settings.yml | 2 +- .../structured_configs/snmp-settings-1.yml | 16 +- .../structured_configs/snmp-settings-2.yml | 4 +- .../structured_configs/source-interfaces.yml | 1 - .../inventory/group_vars/CORE_UNIT_TESTS.yml | 6 + .../UPLINK_MLAG_STRUCTURED_CONFIG_L2LEAFS.yml | 40 +- .../custom-structured-configuration.yml | 13 + .../structured_configs/dc1-leaf1a.yml | 2 +- .../structured_configs/dc1-leaf2c.yml | 2 +- .../structured_configs/dc1-spine1.yml | 30 +- .../dc2-leaf3a.arista.com.yml | 28 +- .../dc2-leaf3b.arista.com.yml | 10 +- .../intended/structured_configs/DC1-BL1A.yml | 18 +- .../intended/structured_configs/DC1-BL1B.yml | 18 +- .../intended/structured_configs/DC1-BL1A.yml | 6 +- .../intended/structured_configs/DC1-BL1B.yml | 6 +- .../avd/plugins/action/eos_designs_facts.py | 10 +- ...rk-services-vrfs-l3-interfaces-settings.md | 4 +- .../network-services-vrfs-svis-settings.md | 8 +- .../tables/node-type-uplink-configuration.md | 16 +- .../eos_designs/docs/tables/svi-profiles.md | 8 +- pylintrc | 5 +- pyproject.toml | 32 +- .../_eos_cli_config_gen/schema/__init__.py | 68849 ++++++++++++++++ python-avd/pyavd/_eos_designs/avdfacts.py | 6 +- .../eos_designs_facts/__init__.py | 45 +- .../_eos_designs/eos_designs_facts/mlag.py | 2 +- .../_eos_designs/eos_designs_facts/overlay.py | 8 +- .../eos_designs_facts/short_esi.py | 8 +- .../_eos_designs/eos_designs_facts/uplinks.py | 60 +- .../_eos_designs/eos_designs_facts/vlans.py | 121 +- .../_eos_designs/eos_designs_facts/wan.py | 6 +- .../pyavd/_eos_designs/schema/__init__.py | 57543 +++++++++++++ .../schema/eos_designs.schema.yml | 4 +- .../defs_network_services.schema.yml | 1 + .../defs_node_type.schema.yml | 1 + .../defs_svi_settings.schema.yml | 2 +- .../_eos_designs/shared_utils/__init__.py | 14 +- .../shared_utils/bgp_peer_groups.py | 70 - .../shared_utils/connected_endpoints_keys.py | 34 - .../_eos_designs/shared_utils/cv_topology.py | 80 +- .../_eos_designs/shared_utils/descriptions.py | 121 - .../shared_utils/filtered_tenants.py | 402 +- .../shared_utils/flow_tracking.py | 112 +- .../shared_utils/inband_management.py | 78 +- .../shared_utils/interface_descriptions.py | 32 +- .../shared_utils/ip_addressing.py | 75 +- .../shared_utils/l3_interfaces.py | 69 +- .../shared_utils/link_tracking_groups.py | 17 +- .../pyavd/_eos_designs/shared_utils/mgmt.py | 34 +- .../pyavd/_eos_designs/shared_utils/misc.py | 304 +- .../pyavd/_eos_designs/shared_utils/mlag.py | 86 +- .../_eos_designs/shared_utils/node_config.py | 99 + .../_eos_designs/shared_utils/node_type.py | 43 +- .../shared_utils/node_type_keys.py | 33 +- .../_eos_designs/shared_utils/overlay.py | 93 +- .../_eos_designs/shared_utils/platform.py | 72 +- .../pyavd/_eos_designs/shared_utils/ptp.py | 30 +- .../_eos_designs/shared_utils/routing.py | 66 +- .../_eos_designs/shared_utils/switch_data.py | 87 - .../_eos_designs/shared_utils/underlay.py | 52 +- .../pyavd/_eos_designs/shared_utils/utils.py | 47 +- .../pyavd/_eos_designs/shared_utils/wan.py | 410 +- .../structured_config/__init__.py | 8 +- .../structured_config/base/__init__.py | 342 +- .../structured_config/base/ntp.py | 25 +- .../structured_config/base/router_general.py | 2 +- .../structured_config/base/snmp_server.py | 153 +- .../structured_config/base/utils.py | 13 +- .../ethernet_interfaces.py | 155 +- .../connected_endpoints/monitor_sessions.py | 107 +- .../port_channel_interfaces.py | 133 +- .../connected_endpoints/utils.py | 187 +- .../core_interfaces_and_l3_edge/__init__.py | 10 + .../ethernet_interfaces.py | 32 +- .../port_channel_interfaces.py | 22 +- .../core_interfaces_and_l3_edge/router_bgp.py | 28 +- .../router_ospf.py | 6 +- .../core_interfaces_and_l3_edge/utils.py | 221 +- .../__init__.py | 24 +- .../structured_config/flows/__init__.py | 117 +- .../inband_management/__init__.py | 18 +- .../metadata/cv_pathfinder.py | 84 +- .../structured_config/metadata/cv_tags.py | 92 +- .../structured_config/mlag/__init__.py | 131 +- .../application_traffic_recognition.py | 204 +- .../network_services/dps_interfaces.py | 2 +- .../network_services/eos_cli.py | 2 +- .../network_services/ethernet_interfaces.py | 123 +- .../network_services/ip_access_lists.py | 20 +- .../network_services/ip_igmp_snooping.py | 89 +- .../network_services/ip_security.py | 12 +- .../ip_virtual_router_mac_address.py | 8 +- .../network_services/ipv6_static_routes.py | 11 +- .../network_services/loopback_interfaces.py | 69 +- .../network_services/metadata.py | 28 +- .../network_services/monitor_connectivity.py | 6 +- .../network_services/patch_panel.py | 38 +- .../port_channel_interfaces.py | 37 +- .../network_services/prefix_lists.py | 2 +- .../network_services/route_maps.py | 14 +- .../router_adaptive_virtual_topology.py | 18 +- .../network_services/router_bgp.py | 614 +- .../network_services/router_internet_exit.py | 12 +- .../network_services/router_multicast.py | 8 +- .../network_services/router_ospf.py | 50 +- .../network_services/router_path_selection.py | 6 +- .../router_pim_sparse_mode.py | 8 +- .../router_service_insertion.py | 18 +- .../network_services/spanning_tree.py | 23 +- .../network_services/standard_access_lists.py | 49 +- .../network_services/static_routes.py | 27 +- .../network_services/struct_cfgs.py | 6 +- .../network_services/tunnel_interfaces.py | 10 +- .../network_services/utils.py | 281 +- .../network_services/utils_wan.py | 387 +- .../network_services/utils_zscaler.py | 82 +- .../network_services/vlan_interfaces.py | 86 +- .../network_services/vlans.py | 38 +- .../network_services/vrfs.py | 25 +- .../network_services/vxlan_interface.py | 208 +- .../structured_config/overlay/cvx.py | 5 +- .../structured_config/overlay/ip_security.py | 15 +- .../overlay/management_cvx.py | 8 +- .../structured_config/overlay/route_maps.py | 4 +- .../router_adaptive_virtual_topology.py | 20 +- .../structured_config/overlay/router_bfd.py | 7 +- .../structured_config/overlay/router_bgp.py | 177 +- .../overlay/router_path_selection.py | 83 +- .../structured_config/overlay/stun.py | 2 +- .../structured_config/overlay/utils.py | 61 +- .../underlay/ethernet_interfaces.py | 93 +- .../underlay/loopback_interfaces.py | 24 +- .../structured_config/underlay/mpls.py | 2 +- .../underlay/port_channel_interfaces.py | 13 +- .../underlay/prefix_lists.py | 8 +- .../structured_config/underlay/route_maps.py | 2 +- .../structured_config/underlay/router_bgp.py | 28 +- .../structured_config/underlay/router_isis.py | 41 +- .../structured_config/underlay/router_msdp.py | 18 +- .../structured_config/underlay/router_ospf.py | 14 +- .../underlay/router_pim_sparse_mode.py | 46 +- .../underlay/standard_access_lists.py | 10 +- .../underlay/static_routes.py | 19 +- .../structured_config/underlay/utils.py | 156 +- python-avd/pyavd/_schema/coerce_type.py | 117 + python-avd/pyavd/_schema/constants.py | 7 + python-avd/pyavd/_schema/models/__init__.py | 3 + python-avd/pyavd/_schema/models/avd_base.py | 68 + .../pyavd/_schema/models/avd_indexed_list.py | 198 + python-avd/pyavd/_schema/models/avd_list.py | 184 + python-avd/pyavd/_schema/models/avd_model.py | 356 + .../models/eos_cli_config_gen_root_model.py | 29 + .../_schema/models/eos_designs_root_model.py | 116 + python-avd/pyavd/_schema/models/type_vars.py | 20 + python-avd/pyavd/_utils/__init__.py | 6 +- python-avd/pyavd/_utils/default.py | 25 +- python-avd/pyavd/_utils/get_all.py | 14 + python-avd/pyavd/_utils/groupby.py | 14 +- python-avd/pyavd/_utils/merge/__init__.py | 2 +- python-avd/pyavd/_utils/undefined.py | 21 + .../api/interface_descriptions/__init__.py | 46 +- .../pyavd/api/ip_addressing/__init__.py | 62 +- python-avd/pyavd/api/ip_addressing/utils.py | 40 +- python-avd/pyavd/get_avd_facts.py | 8 +- python-avd/pyavd/j2filters/natural_sort.py | 18 +- python-avd/pyavd/j2filters/range_expand.py | 10 +- python-avd/pyavd/templater.py | 4 +- python-avd/pyproject.toml | 1 + python-avd/schema_tools/build_schemas.py | 30 +- python-avd/schema_tools/constants.py | 4 + .../schema_tools/generate_classes/__init__.py | 3 + .../generate_classes/class_src_gen.py | 510 + .../generate_classes/src_generators.py | 445 + .../schema_tools/generate_classes/utils.py | 43 + .../metaschema/meta_schema_model.py | 41 +- .../schema_tools/metaschema/resolvemodel.py | 28 +- .../tests/pyavd/j2filters/test_decrypt.py | 12 +- .../tests/pyavd/j2filters/test_encrypt.py | 21 +- .../pyavd/j2filters/test_natural_sort.py | 19 +- .../pyavd/j2filters/test_range_expand.py | 4 +- .../test_eos_cli_config_gen_class.py | 77 + .../test_eos_designs_class.py | 121 + .../test_validate_structured_config.py | 53 +- .../pyavd/utils/password/test_password.py | 14 +- .../utils/password/test_password_utils.py | 20 +- .../schema_tools/artifacts/DC1-BL1A.json | 5032 ++ .../tests/schema_tools/artifacts/README.md | 11 + .../artifacts/eos_cli_config_gen.schema.yml | 10918 ++- .../artifacts/ethernet-interfaces.json | 2460 + .../generate_classes/artifacts/.gitignore | 5 + .../generate_classes/artifacts/__init__.py | 3 + .../generate_classes/test_class_src_gen.py | 70 + .../generate_docs/test_mdtabsgen.py | 12 +- .../metaschema/test_meta_schema_model.py | 2 +- python-avd/tests/utils.py | 5 +- python-avd/tox.ini | 1 - 313 files changed, 153331 insertions(+), 10196 deletions(-) create mode 100644 python-avd/pyavd/_eos_cli_config_gen/schema/__init__.py create mode 100644 python-avd/pyavd/_eos_designs/schema/__init__.py delete mode 100644 python-avd/pyavd/_eos_designs/shared_utils/bgp_peer_groups.py delete mode 100644 python-avd/pyavd/_eos_designs/shared_utils/connected_endpoints_keys.py delete mode 100644 python-avd/pyavd/_eos_designs/shared_utils/descriptions.py create mode 100644 python-avd/pyavd/_eos_designs/shared_utils/node_config.py delete mode 100644 python-avd/pyavd/_eos_designs/shared_utils/switch_data.py create mode 100644 python-avd/pyavd/_schema/coerce_type.py create mode 100644 python-avd/pyavd/_schema/models/__init__.py create mode 100644 python-avd/pyavd/_schema/models/avd_base.py create mode 100644 python-avd/pyavd/_schema/models/avd_indexed_list.py create mode 100644 python-avd/pyavd/_schema/models/avd_list.py create mode 100644 python-avd/pyavd/_schema/models/avd_model.py create mode 100644 python-avd/pyavd/_schema/models/eos_cli_config_gen_root_model.py create mode 100644 python-avd/pyavd/_schema/models/eos_designs_root_model.py create mode 100644 python-avd/pyavd/_schema/models/type_vars.py create mode 100644 python-avd/pyavd/_utils/undefined.py create mode 100644 python-avd/schema_tools/generate_classes/__init__.py create mode 100644 python-avd/schema_tools/generate_classes/class_src_gen.py create mode 100644 python-avd/schema_tools/generate_classes/src_generators.py create mode 100644 python-avd/schema_tools/generate_classes/utils.py create mode 100644 python-avd/tests/pyavd/molecule_scenarios/test_eos_cli_config_gen_class.py create mode 100644 python-avd/tests/pyavd/molecule_scenarios/test_eos_designs_class.py create mode 100644 python-avd/tests/schema_tools/artifacts/DC1-BL1A.json create mode 100644 python-avd/tests/schema_tools/artifacts/README.md create mode 100644 python-avd/tests/schema_tools/artifacts/ethernet-interfaces.json create mode 100644 python-avd/tests/schema_tools/generate_classes/artifacts/.gitignore create mode 100644 python-avd/tests/schema_tools/generate_classes/artifacts/__init__.py create mode 100644 python-avd/tests/schema_tools/generate_classes/test_class_src_gen.py diff --git a/.gitattributes b/.gitattributes index 9b4e1240e7c..a24aef70e3f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,8 @@ # Collapsing generated schemas from PR diff by default /python-avd/pyavd/_eos_cli_config_gen/schema/eos_cli_config_gen.schema.yml linguist-generated=true -merge -diff /python-avd/pyavd/_eos_designs/schema/eos_designs.schema.yml linguist-generated=true -merge -diff +/python-avd/pyavd/_eos_cli_config_gen/schema/__init__.py linguist-generated=true -merge -diff +/python-avd/pyavd/_eos_designs/schema/__init__.py linguist-generated=true -merge -diff # Showing generated tables in PR diff by default by count as generated and automatically use the latest file on merge /ansible_collections/arista/avd/roles/eos_cli_config_gen/docs/tables/* linguist-generated=true -merge diff diff --git a/.github/yamllintrc b/.github/yamllintrc index 35073d2e874..2ba8cf9b360 100644 --- a/.github/yamllintrc +++ b/.github/yamllintrc @@ -47,6 +47,7 @@ rules: - /ansible_collections/arista/avd/changelogs/fragments_backup/ - /ansible_collections/arista/avd/tests/inventory/**/expected_output/ - /python-avd/pyavd/**/schema/ + - /python-avd/tests/**/artifacts/ - /.github/workflows/ new-lines: type: unix diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fe1f02e3b15..e534c22ad0a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: exclude: ansible_collections/arista/avd/molecule - id: check-added-large-files name: Prevents giant files from being committed. - exclude: (ansible_collections/arista/avd/molecule|pickle$) + exclude: (ansible_collections/arista/avd/molecule|pickle$|python-avd/pyavd/_(eos_cli_config_gen|eos_designs)/schema/__init__.py) - id: check-merge-conflict name: Checks for files that contain merge conflict strings. exclude: ansible_collections/arista/avd/molecule @@ -202,7 +202,7 @@ repos: language: python files: python-avd/pyavd/[a-z_]+/schema pass_filenames: false - additional_dependencies: ['deepmerge>=1.1.0', 'PyYAML>=6.0.0', 'pydantic>=2.3.0', 'jsonschema-rs>=0.24', 'referencing>=0.35.0'] + additional_dependencies: ['deepmerge>=1.1.0', 'PyYAML>=6.0.0', 'pydantic>=2.3.0', 'jsonschema-rs>=0.24', 'referencing>=0.35.0', 'ruff==0.7.2'] - id: templates name: Precompile Jinja2 templates diff --git a/.sonarcloud.properties b/.sonarcloud.properties index c271233fbd8..4acf196fbe0 100644 --- a/.sonarcloud.properties +++ b/.sonarcloud.properties @@ -1,6 +1,6 @@ # Python version sonar.python.version=3.10, 3.11, 3.12, 3.13 -# Exclude tests from source -sonar.exclusions=python-avd/tests/** +# Exclude generated classes +sonar.exclusions=python-avd/pyavd/_eos_cli_config_gen/schema/__init__.py,python-avd/pyavd/_eos_designs/schema/__init__.py # Path to tests -sonar.tests=python-avd/tests +sonar.tests=python-avd/tests/ diff --git a/ansible_collections/arista/avd/docs/release-notes/5.x.x.md b/ansible_collections/arista/avd/docs/release-notes/5.x.x.md index fcbd26b8138..cd489d49b96 100644 --- a/ansible_collections/arista/avd/docs/release-notes/5.x.x.md +++ b/ansible_collections/arista/avd/docs/release-notes/5.x.x.md @@ -10,7 +10,33 @@ title: Release Notes for AVD 5.x.x # Release Notes for AVD 5.x.x -- Documentation for AVD version `5.x.x` [available here](https://avd.arista.com/stable/) +- Documentation for AVD version `5.x.x` [available here](https://avd.arista.com/5.x/) + +## Release 5.2.0 + +### Fix for merging of node variables if a device is defined twice + +With variables like below, where `myswitch1` is specified both under the `nodes` and under `node_groups[].nodes`, +AVD would wrongfully ignore the variables under the `node_groups[]` and `node_groups[].nodes` in versions below 5.1. + +```yaml +: + nodes: + - name: myswitch1 + id: 1 + + # Everything below node_groups would be ignored in older versions for devices found under `nodes`. + node_groups: + - group: mygroup1 + filters: + tags: + - mytag + nodes: + - name: myswitch1 + mgmt_ip: 192.168.200.10/24 +``` + +Starting with version 5.2 AVD follows the [documented behavior](https://avd.arista.com/5.0/roles/eos_designs/docs/input-variables.html#node-type-structure). ## Release 5.1.0 diff --git a/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF1A.yml b/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF1A.yml index 51fefc35e2a..889e3869ef0 100644 --- a/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF1A.yml +++ b/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF1A.yml @@ -147,6 +147,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -156,17 +159,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet2 @@ -179,6 +179,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -188,17 +191,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3 @@ -211,6 +211,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -220,17 +223,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4 @@ -243,6 +243,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -252,17 +255,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5 @@ -275,6 +275,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -284,17 +287,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6 @@ -307,6 +307,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -316,17 +319,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7 @@ -339,6 +339,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -348,17 +351,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet8 @@ -371,6 +371,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -380,17 +383,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet9 @@ -403,6 +403,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -412,17 +415,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet10 @@ -435,6 +435,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -444,17 +447,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet11 @@ -467,6 +467,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -476,17 +479,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet12 @@ -499,6 +499,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -508,17 +511,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet13 @@ -531,6 +531,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -540,17 +543,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet14 @@ -563,6 +563,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -572,17 +575,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet15 @@ -595,6 +595,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -604,17 +607,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet16 @@ -627,6 +627,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -636,17 +639,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet17 @@ -659,6 +659,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -668,17 +671,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet18 @@ -691,6 +691,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -700,17 +703,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet19 @@ -723,6 +723,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -732,17 +735,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet20 @@ -755,6 +755,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -764,17 +767,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet21 @@ -787,6 +787,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -796,17 +799,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet22 @@ -819,6 +819,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -828,17 +831,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet23 @@ -851,6 +851,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -860,17 +863,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet24 @@ -883,6 +883,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -892,17 +895,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet25 @@ -915,6 +915,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -924,17 +927,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet26 @@ -947,6 +947,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -956,17 +959,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet27 @@ -979,6 +979,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -988,17 +991,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet28 @@ -1011,6 +1011,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1020,17 +1023,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet29 @@ -1043,6 +1043,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1052,17 +1055,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet30 @@ -1075,6 +1075,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1084,17 +1087,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet31 @@ -1107,6 +1107,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1116,17 +1119,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet32 @@ -1139,6 +1139,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1148,17 +1151,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet33 @@ -1171,6 +1171,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1180,17 +1183,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet34 @@ -1203,6 +1203,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1212,17 +1215,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet35 @@ -1235,6 +1235,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1244,17 +1247,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet36 @@ -1267,6 +1267,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1276,17 +1279,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet37 @@ -1299,6 +1299,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1308,17 +1311,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet38 @@ -1331,6 +1331,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1340,17 +1343,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet39 @@ -1363,6 +1363,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1372,17 +1375,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet40 @@ -1395,6 +1395,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1404,17 +1407,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet41 @@ -1427,6 +1427,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1436,17 +1439,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet42 @@ -1459,6 +1459,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1468,17 +1471,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet43 @@ -1491,6 +1491,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1500,17 +1503,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet44 @@ -1523,6 +1523,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1532,17 +1535,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet45 @@ -1555,6 +1555,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1564,17 +1567,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet46 @@ -1587,6 +1587,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1596,17 +1599,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet47 @@ -1619,6 +1619,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1628,17 +1631,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet48 @@ -1651,6 +1651,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1660,17 +1663,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled mlag_configuration: diff --git a/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF1B.yml b/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF1B.yml index 3c07daefbf2..bce856bf86e 100644 --- a/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF1B.yml +++ b/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF1B.yml @@ -147,6 +147,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -156,17 +159,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet2 @@ -179,6 +179,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -188,17 +191,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3 @@ -211,6 +211,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -220,17 +223,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4 @@ -243,6 +243,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -252,17 +255,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5 @@ -275,6 +275,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -284,17 +287,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6 @@ -307,6 +307,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -316,17 +319,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7 @@ -339,6 +339,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -348,17 +351,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet8 @@ -371,6 +371,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -380,17 +383,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet9 @@ -403,6 +403,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -412,17 +415,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet10 @@ -435,6 +435,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -444,17 +447,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet11 @@ -467,6 +467,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -476,17 +479,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet12 @@ -499,6 +499,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -508,17 +511,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet13 @@ -531,6 +531,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -540,17 +543,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet14 @@ -563,6 +563,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -572,17 +575,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet15 @@ -595,6 +595,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -604,17 +607,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet16 @@ -627,6 +627,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -636,17 +639,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet17 @@ -659,6 +659,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -668,17 +671,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet18 @@ -691,6 +691,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -700,17 +703,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet19 @@ -723,6 +723,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -732,17 +735,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet20 @@ -755,6 +755,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -764,17 +767,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet21 @@ -787,6 +787,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -796,17 +799,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet22 @@ -819,6 +819,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -828,17 +831,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet23 @@ -851,6 +851,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -860,17 +863,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet24 @@ -883,6 +883,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -892,17 +895,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet25 @@ -915,6 +915,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -924,17 +927,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet26 @@ -947,6 +947,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -956,17 +959,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet27 @@ -979,6 +979,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -988,17 +991,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet28 @@ -1011,6 +1011,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1020,17 +1023,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet29 @@ -1043,6 +1043,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1052,17 +1055,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet30 @@ -1075,6 +1075,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1084,17 +1087,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet31 @@ -1107,6 +1107,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1116,17 +1119,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet32 @@ -1139,6 +1139,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1148,17 +1151,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet33 @@ -1171,6 +1171,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1180,17 +1183,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet34 @@ -1203,6 +1203,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1212,17 +1215,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet35 @@ -1235,6 +1235,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1244,17 +1247,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet36 @@ -1267,6 +1267,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1276,17 +1279,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet37 @@ -1299,6 +1299,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1308,17 +1311,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet38 @@ -1331,6 +1331,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1340,17 +1343,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet39 @@ -1363,6 +1363,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1372,17 +1375,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet40 @@ -1395,6 +1395,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1404,17 +1407,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet41 @@ -1427,6 +1427,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1436,17 +1439,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet42 @@ -1459,6 +1459,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1468,17 +1471,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet43 @@ -1491,6 +1491,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1500,17 +1503,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet44 @@ -1523,6 +1523,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1532,17 +1535,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet45 @@ -1555,6 +1555,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1564,17 +1567,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet46 @@ -1587,6 +1587,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1596,17 +1599,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet47 @@ -1619,6 +1619,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1628,17 +1631,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet48 @@ -1651,6 +1651,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 130 host_mode: mode: multi-host multi_host_authenticated: true @@ -1660,17 +1663,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 130 switchport: enabled: true mode: trunk phone trunk: native_vlan: 110 phone: - trunk: untagged vlan: 120 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled mlag_configuration: diff --git a/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF2A.yml b/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF2A.yml index 3858d2a20a0..7e39c4ddb0a 100644 --- a/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF2A.yml +++ b/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF2A.yml @@ -87,6 +87,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -96,9 +99,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -115,8 +115,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/2 @@ -129,6 +129,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -138,9 +141,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -157,8 +157,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/3 @@ -171,6 +171,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -180,9 +183,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -199,8 +199,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/4 @@ -213,6 +213,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -222,9 +225,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -241,8 +241,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/5 @@ -255,6 +255,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -264,9 +267,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -283,8 +283,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/6 @@ -297,6 +297,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -306,9 +309,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -325,8 +325,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/7 @@ -339,6 +339,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -348,9 +351,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -367,8 +367,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/8 @@ -381,6 +381,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -390,9 +393,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -409,8 +409,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/9 @@ -423,6 +423,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -432,9 +435,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -451,8 +451,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/10 @@ -465,6 +465,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -474,9 +477,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -493,8 +493,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/11 @@ -507,6 +507,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -516,9 +519,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -535,8 +535,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/12 @@ -549,6 +549,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -558,9 +561,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -577,8 +577,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/13 @@ -591,6 +591,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -600,9 +603,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -619,8 +619,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/14 @@ -633,6 +633,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -642,9 +645,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -661,8 +661,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/15 @@ -675,6 +675,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -684,9 +687,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -703,8 +703,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/16 @@ -717,6 +717,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -726,9 +729,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -745,8 +745,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/17 @@ -759,6 +759,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -768,9 +771,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -787,8 +787,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/18 @@ -801,6 +801,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -810,9 +813,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -829,8 +829,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/19 @@ -843,6 +843,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -852,9 +855,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -871,8 +871,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/20 @@ -885,6 +885,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -894,9 +897,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -913,8 +913,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/21 @@ -927,6 +927,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -936,9 +939,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -955,8 +955,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/22 @@ -969,6 +969,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -978,9 +981,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -997,8 +997,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/23 @@ -1011,6 +1011,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1020,9 +1023,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1039,8 +1039,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/24 @@ -1053,6 +1053,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1062,9 +1065,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1081,8 +1081,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/25 @@ -1095,6 +1095,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1104,9 +1107,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1123,8 +1123,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/26 @@ -1137,6 +1137,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1146,9 +1149,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1165,8 +1165,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/27 @@ -1179,6 +1179,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1188,9 +1191,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1207,8 +1207,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/28 @@ -1221,6 +1221,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1230,9 +1233,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1249,8 +1249,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/29 @@ -1263,6 +1263,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1272,9 +1275,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1291,8 +1291,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/30 @@ -1305,6 +1305,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1314,9 +1317,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1333,8 +1333,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/31 @@ -1347,6 +1347,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1356,9 +1359,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1375,8 +1375,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/32 @@ -1389,6 +1389,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1398,9 +1401,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1417,8 +1417,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/33 @@ -1431,6 +1431,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1440,9 +1443,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1459,8 +1459,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/34 @@ -1473,6 +1473,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1482,9 +1485,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1501,8 +1501,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/35 @@ -1515,6 +1515,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1524,9 +1527,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1543,8 +1543,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/36 @@ -1557,6 +1557,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1566,9 +1569,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1585,8 +1585,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/37 @@ -1599,6 +1599,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1608,9 +1611,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1627,8 +1627,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/38 @@ -1641,6 +1641,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1650,9 +1653,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1669,8 +1669,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/39 @@ -1683,6 +1683,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1692,9 +1695,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1711,8 +1711,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/40 @@ -1725,6 +1725,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1734,9 +1737,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1753,8 +1753,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/41 @@ -1767,6 +1767,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1776,9 +1779,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1795,8 +1795,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/42 @@ -1809,6 +1809,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1818,9 +1821,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1837,8 +1837,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/43 @@ -1851,6 +1851,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1860,9 +1863,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1879,8 +1879,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/44 @@ -1893,6 +1893,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1902,9 +1905,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1921,8 +1921,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/45 @@ -1935,6 +1935,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1944,9 +1947,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -1963,8 +1963,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/46 @@ -1977,6 +1977,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -1986,9 +1989,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2005,8 +2005,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/47 @@ -2019,6 +2019,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2028,9 +2031,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2047,8 +2047,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3/48 @@ -2061,6 +2061,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2070,9 +2073,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2089,8 +2089,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/1 @@ -2103,6 +2103,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2112,9 +2115,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2131,8 +2131,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/2 @@ -2145,6 +2145,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2154,9 +2157,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2173,8 +2173,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/3 @@ -2187,6 +2187,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2196,9 +2199,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2215,8 +2215,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/4 @@ -2229,6 +2229,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2238,9 +2241,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2257,8 +2257,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/5 @@ -2271,6 +2271,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2280,9 +2283,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2299,8 +2299,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/6 @@ -2313,6 +2313,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2322,9 +2325,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2341,8 +2341,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/7 @@ -2355,6 +2355,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2364,9 +2367,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2383,8 +2383,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/8 @@ -2397,6 +2397,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2406,9 +2409,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2425,8 +2425,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/9 @@ -2439,6 +2439,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2448,9 +2451,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2467,8 +2467,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/10 @@ -2481,6 +2481,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2490,9 +2493,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2509,8 +2509,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/11 @@ -2523,6 +2523,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2532,9 +2535,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2551,8 +2551,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/12 @@ -2565,6 +2565,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2574,9 +2577,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2593,8 +2593,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/13 @@ -2607,6 +2607,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2616,9 +2619,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2635,8 +2635,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/14 @@ -2649,6 +2649,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2658,9 +2661,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2677,8 +2677,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/15 @@ -2691,6 +2691,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2700,9 +2703,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2719,8 +2719,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/16 @@ -2733,6 +2733,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2742,9 +2745,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2761,8 +2761,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/17 @@ -2775,6 +2775,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2784,9 +2787,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2803,8 +2803,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/18 @@ -2817,6 +2817,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2826,9 +2829,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2845,8 +2845,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/19 @@ -2859,6 +2859,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2868,9 +2871,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2887,8 +2887,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/20 @@ -2901,6 +2901,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2910,9 +2913,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2929,8 +2929,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/21 @@ -2943,6 +2943,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2952,9 +2955,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -2971,8 +2971,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/22 @@ -2985,6 +2985,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -2994,9 +2997,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3013,8 +3013,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/23 @@ -3027,6 +3027,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3036,9 +3039,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3055,8 +3055,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/24 @@ -3069,6 +3069,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3078,9 +3081,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3097,8 +3097,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/25 @@ -3111,6 +3111,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3120,9 +3123,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3139,8 +3139,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/26 @@ -3153,6 +3153,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3162,9 +3165,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3181,8 +3181,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/27 @@ -3195,6 +3195,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3204,9 +3207,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3223,8 +3223,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/28 @@ -3237,6 +3237,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3246,9 +3249,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3265,8 +3265,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/29 @@ -3279,6 +3279,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3288,9 +3291,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3307,8 +3307,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/30 @@ -3321,6 +3321,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3330,9 +3333,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3349,8 +3349,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/31 @@ -3363,6 +3363,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3372,9 +3375,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3391,8 +3391,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/32 @@ -3405,6 +3405,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3414,9 +3417,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3433,8 +3433,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/33 @@ -3447,6 +3447,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3456,9 +3459,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3475,8 +3475,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/34 @@ -3489,6 +3489,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3498,9 +3501,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3517,8 +3517,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/35 @@ -3531,6 +3531,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3540,9 +3543,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3559,8 +3559,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/36 @@ -3573,6 +3573,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3582,9 +3585,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3601,8 +3601,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/37 @@ -3615,6 +3615,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3624,9 +3627,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3643,8 +3643,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/38 @@ -3657,6 +3657,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3666,9 +3669,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3685,8 +3685,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/39 @@ -3699,6 +3699,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3708,9 +3711,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3727,8 +3727,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/40 @@ -3741,6 +3741,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3750,9 +3753,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3769,8 +3769,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/41 @@ -3783,6 +3783,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3792,9 +3795,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3811,8 +3811,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/42 @@ -3825,6 +3825,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3834,9 +3837,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3853,8 +3853,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/43 @@ -3867,6 +3867,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3876,9 +3879,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3895,8 +3895,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/44 @@ -3909,6 +3909,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3918,9 +3921,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3937,8 +3937,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/45 @@ -3951,6 +3951,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -3960,9 +3963,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -3979,8 +3979,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/46 @@ -3993,6 +3993,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4002,9 +4005,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4021,8 +4021,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/47 @@ -4035,6 +4035,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4044,9 +4047,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4063,8 +4063,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4/48 @@ -4077,6 +4077,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4086,9 +4089,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4105,8 +4105,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/1 @@ -4119,6 +4119,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4128,9 +4131,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4147,8 +4147,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/2 @@ -4161,6 +4161,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4170,9 +4173,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4189,8 +4189,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/3 @@ -4203,6 +4203,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4212,9 +4215,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4231,8 +4231,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/4 @@ -4245,6 +4245,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4254,9 +4257,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4273,8 +4273,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/5 @@ -4287,6 +4287,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4296,9 +4299,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4315,8 +4315,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/6 @@ -4329,6 +4329,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4338,9 +4341,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4357,8 +4357,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/7 @@ -4371,6 +4371,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4380,9 +4383,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4399,8 +4399,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/8 @@ -4413,6 +4413,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4422,9 +4425,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4441,8 +4441,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/9 @@ -4455,6 +4455,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4464,9 +4467,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4483,8 +4483,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/10 @@ -4497,6 +4497,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4506,9 +4509,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4525,8 +4525,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/11 @@ -4539,6 +4539,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4548,9 +4551,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4567,8 +4567,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/12 @@ -4581,6 +4581,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4590,9 +4593,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4609,8 +4609,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/13 @@ -4623,6 +4623,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4632,9 +4635,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4651,8 +4651,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/14 @@ -4665,6 +4665,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4674,9 +4677,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4693,8 +4693,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/15 @@ -4707,6 +4707,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4716,9 +4719,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4735,8 +4735,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/16 @@ -4749,6 +4749,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4758,9 +4761,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4777,8 +4777,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/17 @@ -4791,6 +4791,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4800,9 +4803,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4819,8 +4819,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/18 @@ -4833,6 +4833,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4842,9 +4845,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4861,8 +4861,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/19 @@ -4875,6 +4875,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4884,9 +4887,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4903,8 +4903,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/20 @@ -4917,6 +4917,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4926,9 +4929,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4945,8 +4945,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/21 @@ -4959,6 +4959,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -4968,9 +4971,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -4987,8 +4987,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/22 @@ -5001,6 +5001,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5010,9 +5013,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5029,8 +5029,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/23 @@ -5043,6 +5043,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5052,9 +5055,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5071,8 +5071,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/24 @@ -5085,6 +5085,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5094,9 +5097,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5113,8 +5113,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/25 @@ -5127,6 +5127,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5136,9 +5139,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5155,8 +5155,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/26 @@ -5169,6 +5169,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5178,9 +5181,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5197,8 +5197,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/27 @@ -5211,6 +5211,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5220,9 +5223,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5239,8 +5239,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/28 @@ -5253,6 +5253,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5262,9 +5265,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5281,8 +5281,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/29 @@ -5295,6 +5295,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5304,9 +5307,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5323,8 +5323,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/30 @@ -5337,6 +5337,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5346,9 +5349,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5365,8 +5365,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/31 @@ -5379,6 +5379,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5388,9 +5391,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5407,8 +5407,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/32 @@ -5421,6 +5421,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5430,9 +5433,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5449,8 +5449,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/33 @@ -5463,6 +5463,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5472,9 +5475,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5491,8 +5491,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/34 @@ -5505,6 +5505,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5514,9 +5517,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5533,8 +5533,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/35 @@ -5547,6 +5547,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5556,9 +5559,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5575,8 +5575,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/36 @@ -5589,6 +5589,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5598,9 +5601,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5617,8 +5617,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/37 @@ -5631,6 +5631,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5640,9 +5643,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5659,8 +5659,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/38 @@ -5673,6 +5673,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5682,9 +5685,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5701,8 +5701,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/39 @@ -5715,6 +5715,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5724,9 +5727,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5743,8 +5743,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/40 @@ -5757,6 +5757,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5766,9 +5769,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5785,8 +5785,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/41 @@ -5799,6 +5799,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5808,9 +5811,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5827,8 +5827,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/42 @@ -5841,6 +5841,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5850,9 +5853,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5869,8 +5869,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/43 @@ -5883,6 +5883,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5892,9 +5895,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5911,8 +5911,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/44 @@ -5925,6 +5925,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5934,9 +5937,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5953,8 +5953,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/45 @@ -5967,6 +5967,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -5976,9 +5979,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -5995,8 +5995,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/46 @@ -6009,6 +6009,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6018,9 +6021,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6037,8 +6037,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/47 @@ -6051,6 +6051,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6060,9 +6063,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6079,8 +6079,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5/48 @@ -6093,6 +6093,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6102,9 +6105,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6121,8 +6121,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/1 @@ -6135,6 +6135,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6144,9 +6147,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6163,8 +6163,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/2 @@ -6177,6 +6177,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6186,9 +6189,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6205,8 +6205,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/3 @@ -6219,6 +6219,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6228,9 +6231,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6247,8 +6247,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/4 @@ -6261,6 +6261,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6270,9 +6273,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6289,8 +6289,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/5 @@ -6303,6 +6303,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6312,9 +6315,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6331,8 +6331,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/6 @@ -6345,6 +6345,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6354,9 +6357,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6373,8 +6373,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/7 @@ -6387,6 +6387,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6396,9 +6399,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6415,8 +6415,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/8 @@ -6429,6 +6429,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6438,9 +6441,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6457,8 +6457,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/9 @@ -6471,6 +6471,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6480,9 +6483,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6499,8 +6499,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/10 @@ -6513,6 +6513,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6522,9 +6525,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6541,8 +6541,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/11 @@ -6555,6 +6555,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6564,9 +6567,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6583,8 +6583,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/12 @@ -6597,6 +6597,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6606,9 +6609,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6625,8 +6625,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/13 @@ -6639,6 +6639,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6648,9 +6651,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6667,8 +6667,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/14 @@ -6681,6 +6681,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6690,9 +6693,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6709,8 +6709,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/15 @@ -6723,6 +6723,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6732,9 +6735,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6751,8 +6751,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/16 @@ -6765,6 +6765,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6774,9 +6777,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6793,8 +6793,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/17 @@ -6807,6 +6807,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6816,9 +6819,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6835,8 +6835,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/18 @@ -6849,6 +6849,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6858,9 +6861,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6877,8 +6877,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/19 @@ -6891,6 +6891,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6900,9 +6903,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6919,8 +6919,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/20 @@ -6933,6 +6933,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6942,9 +6945,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -6961,8 +6961,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/21 @@ -6975,6 +6975,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -6984,9 +6987,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7003,8 +7003,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/22 @@ -7017,6 +7017,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7026,9 +7029,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7045,8 +7045,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/23 @@ -7059,6 +7059,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7068,9 +7071,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7087,8 +7087,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/24 @@ -7101,6 +7101,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7110,9 +7113,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7129,8 +7129,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/25 @@ -7143,6 +7143,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7152,9 +7155,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7171,8 +7171,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/26 @@ -7185,6 +7185,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7194,9 +7197,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7213,8 +7213,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/27 @@ -7227,6 +7227,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7236,9 +7239,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7255,8 +7255,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/28 @@ -7269,6 +7269,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7278,9 +7281,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7297,8 +7297,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/29 @@ -7311,6 +7311,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7320,9 +7323,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7339,8 +7339,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/30 @@ -7353,6 +7353,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7362,9 +7365,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7381,8 +7381,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/31 @@ -7395,6 +7395,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7404,9 +7407,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7423,8 +7423,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/32 @@ -7437,6 +7437,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7446,9 +7449,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7465,8 +7465,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/33 @@ -7479,6 +7479,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7488,9 +7491,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7507,8 +7507,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/34 @@ -7521,6 +7521,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7530,9 +7533,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7549,8 +7549,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/35 @@ -7563,6 +7563,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7572,9 +7575,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7591,8 +7591,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/36 @@ -7605,6 +7605,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7614,9 +7617,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7633,8 +7633,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/37 @@ -7647,6 +7647,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7656,9 +7659,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7675,8 +7675,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/38 @@ -7689,6 +7689,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7698,9 +7701,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7717,8 +7717,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/39 @@ -7731,6 +7731,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7740,9 +7743,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7759,8 +7759,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/40 @@ -7773,6 +7773,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7782,9 +7785,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7801,8 +7801,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/41 @@ -7815,6 +7815,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7824,9 +7827,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7843,8 +7843,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/42 @@ -7857,6 +7857,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7866,9 +7869,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7885,8 +7885,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/43 @@ -7899,6 +7899,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7908,9 +7911,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7927,8 +7927,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/44 @@ -7941,6 +7941,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7950,9 +7953,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -7969,8 +7969,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/45 @@ -7983,6 +7983,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -7992,9 +7995,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8011,8 +8011,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/46 @@ -8025,6 +8025,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8034,9 +8037,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8053,8 +8053,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/47 @@ -8067,6 +8067,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8076,9 +8079,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8095,8 +8095,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6/48 @@ -8109,6 +8109,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8118,9 +8121,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8137,8 +8137,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/1 @@ -8151,6 +8151,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8160,9 +8163,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8179,8 +8179,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/2 @@ -8193,6 +8193,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8202,9 +8205,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8221,8 +8221,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/3 @@ -8235,6 +8235,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8244,9 +8247,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8263,8 +8263,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/4 @@ -8277,6 +8277,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8286,9 +8289,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8305,8 +8305,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/5 @@ -8319,6 +8319,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8328,9 +8331,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8347,8 +8347,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/6 @@ -8361,6 +8361,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8370,9 +8373,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8389,8 +8389,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/7 @@ -8403,6 +8403,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8412,9 +8415,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8431,8 +8431,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/8 @@ -8445,6 +8445,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8454,9 +8457,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8473,8 +8473,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/9 @@ -8487,6 +8487,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8496,9 +8499,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8515,8 +8515,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/10 @@ -8529,6 +8529,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8538,9 +8541,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8557,8 +8557,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/11 @@ -8571,6 +8571,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8580,9 +8583,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8599,8 +8599,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/12 @@ -8613,6 +8613,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8622,9 +8625,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8641,8 +8641,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/13 @@ -8655,6 +8655,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8664,9 +8667,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8683,8 +8683,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/14 @@ -8697,6 +8697,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8706,9 +8709,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8725,8 +8725,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/15 @@ -8739,6 +8739,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8748,9 +8751,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8767,8 +8767,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/16 @@ -8781,6 +8781,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8790,9 +8793,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8809,8 +8809,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/17 @@ -8823,6 +8823,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8832,9 +8835,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8851,8 +8851,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/18 @@ -8865,6 +8865,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8874,9 +8877,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8893,8 +8893,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/19 @@ -8907,6 +8907,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8916,9 +8919,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8935,8 +8935,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/20 @@ -8949,6 +8949,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -8958,9 +8961,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -8977,8 +8977,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/21 @@ -8991,6 +8991,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9000,9 +9003,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9019,8 +9019,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/22 @@ -9033,6 +9033,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9042,9 +9045,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9061,8 +9061,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/23 @@ -9075,6 +9075,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9084,9 +9087,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9103,8 +9103,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/24 @@ -9117,6 +9117,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9126,9 +9129,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9145,8 +9145,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/25 @@ -9159,6 +9159,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9168,9 +9171,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9187,8 +9187,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/26 @@ -9201,6 +9201,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9210,9 +9213,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9229,8 +9229,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/27 @@ -9243,6 +9243,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9252,9 +9255,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9271,8 +9271,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/28 @@ -9285,6 +9285,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9294,9 +9297,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9313,8 +9313,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/29 @@ -9327,6 +9327,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9336,9 +9339,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9355,8 +9355,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/30 @@ -9369,6 +9369,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9378,9 +9381,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9397,8 +9397,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/31 @@ -9411,6 +9411,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9420,9 +9423,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9439,8 +9439,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/32 @@ -9453,6 +9453,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9462,9 +9465,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9481,8 +9481,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/33 @@ -9495,6 +9495,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9504,9 +9507,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9523,8 +9523,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/34 @@ -9537,6 +9537,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9546,9 +9549,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9565,8 +9565,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/35 @@ -9579,6 +9579,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9588,9 +9591,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9607,8 +9607,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/36 @@ -9621,6 +9621,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9630,9 +9633,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9649,8 +9649,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/37 @@ -9663,6 +9663,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9672,9 +9675,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9691,8 +9691,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/38 @@ -9705,6 +9705,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9714,9 +9717,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9733,8 +9733,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/39 @@ -9747,6 +9747,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9756,9 +9759,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9775,8 +9775,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/40 @@ -9789,6 +9789,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9798,9 +9801,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9817,8 +9817,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/41 @@ -9831,6 +9831,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9840,9 +9843,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9859,8 +9859,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/42 @@ -9873,6 +9873,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9882,9 +9885,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9901,8 +9901,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/43 @@ -9915,6 +9915,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9924,9 +9927,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9943,8 +9943,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/44 @@ -9957,6 +9957,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -9966,9 +9969,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -9985,8 +9985,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/45 @@ -9999,6 +9999,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -10008,9 +10011,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -10027,8 +10027,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/46 @@ -10041,6 +10041,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -10050,9 +10053,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -10069,8 +10069,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/47 @@ -10083,6 +10083,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -10092,9 +10095,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -10111,8 +10111,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7/48 @@ -10125,6 +10125,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 230 host_mode: mode: multi-host multi_host_authenticated: true @@ -10134,9 +10137,6 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 230 poe: priority: critical reboot: @@ -10153,8 +10153,8 @@ ethernet_interfaces: trunk: native_vlan: 210 phone: - trunk: untagged vlan: 220 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled port_channel_interfaces: diff --git a/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3A.yml b/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3A.yml index 43c8d658677..6f2c70c56db 100644 --- a/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3A.yml +++ b/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3A.yml @@ -210,6 +210,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -219,17 +222,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet2 @@ -242,6 +242,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -251,17 +254,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3 @@ -274,6 +274,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -283,17 +286,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4 @@ -306,6 +306,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -315,17 +318,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5 @@ -338,6 +338,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -347,17 +350,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6 @@ -370,6 +370,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -379,17 +382,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7 @@ -402,6 +402,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -411,17 +414,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet8 @@ -434,6 +434,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -443,17 +446,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet9 @@ -466,6 +466,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -475,17 +478,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet10 @@ -498,6 +498,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -507,17 +510,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet11 @@ -530,6 +530,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -539,17 +542,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet12 @@ -562,6 +562,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -571,17 +574,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet13 @@ -594,6 +594,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -603,17 +606,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet14 @@ -626,6 +626,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -635,17 +638,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet15 @@ -658,6 +658,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -667,17 +670,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet16 @@ -690,6 +690,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -699,17 +702,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet17 @@ -722,6 +722,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -731,17 +734,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet18 @@ -754,6 +754,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -763,17 +766,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet19 @@ -786,6 +786,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -795,17 +798,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet20 @@ -818,6 +818,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -827,17 +830,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet21 @@ -850,6 +850,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -859,17 +862,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet22 @@ -882,6 +882,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -891,17 +894,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet23 @@ -914,6 +914,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -923,17 +926,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet24 @@ -946,6 +946,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -955,17 +958,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet25 @@ -978,6 +978,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -987,17 +990,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet26 @@ -1010,6 +1010,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1019,17 +1022,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet27 @@ -1042,6 +1042,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1051,17 +1054,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet28 @@ -1074,6 +1074,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1083,17 +1086,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet29 @@ -1106,6 +1106,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1115,17 +1118,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet30 @@ -1138,6 +1138,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1147,17 +1150,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet31 @@ -1170,6 +1170,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1179,17 +1182,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet32 @@ -1202,6 +1202,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1211,17 +1214,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet33 @@ -1234,6 +1234,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1243,17 +1246,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet34 @@ -1266,6 +1266,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1275,17 +1278,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet35 @@ -1298,6 +1298,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1307,17 +1310,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet36 @@ -1330,6 +1330,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1339,17 +1342,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet37 @@ -1362,6 +1362,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1371,17 +1374,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet38 @@ -1394,6 +1394,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1403,17 +1406,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet39 @@ -1426,6 +1426,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1435,17 +1438,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet40 @@ -1458,6 +1458,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1467,17 +1470,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet41 @@ -1490,6 +1490,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1499,17 +1502,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet42 @@ -1522,6 +1522,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1531,17 +1534,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet43 @@ -1554,6 +1554,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1563,17 +1566,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet44 @@ -1586,6 +1586,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1595,17 +1598,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet45 @@ -1618,6 +1618,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1627,17 +1630,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet46 @@ -1650,6 +1650,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1659,17 +1662,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet47 @@ -1682,6 +1682,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1691,17 +1694,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet48 @@ -1714,6 +1714,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1723,17 +1726,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet49 @@ -1746,6 +1746,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1755,17 +1758,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet50 @@ -1778,6 +1778,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1787,17 +1790,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet51 @@ -1810,6 +1810,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1819,17 +1822,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet52 @@ -1842,6 +1842,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1851,17 +1854,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet53 @@ -1874,6 +1874,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1883,17 +1886,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet54 @@ -1906,6 +1906,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1915,17 +1918,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet55 @@ -1938,6 +1938,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1947,17 +1950,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet56 @@ -1970,6 +1970,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1979,17 +1982,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet57 @@ -2002,6 +2002,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2011,17 +2014,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet58 @@ -2034,6 +2034,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2043,17 +2046,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet59 @@ -2066,6 +2066,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2075,17 +2078,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet60 @@ -2098,6 +2098,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2107,17 +2110,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet61 @@ -2130,6 +2130,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2139,17 +2142,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet62 @@ -2162,6 +2162,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2171,17 +2174,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet63 @@ -2194,6 +2194,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2203,17 +2206,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet64 @@ -2226,6 +2226,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2235,17 +2238,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet65 @@ -2258,6 +2258,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2267,17 +2270,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet66 @@ -2290,6 +2290,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2299,17 +2302,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet67 @@ -2322,6 +2322,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2331,17 +2334,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet68 @@ -2354,6 +2354,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2363,17 +2366,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet69 @@ -2386,6 +2386,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2395,17 +2398,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet70 @@ -2418,6 +2418,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2427,17 +2430,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet71 @@ -2450,6 +2450,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2459,17 +2462,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet72 @@ -2482,6 +2482,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2491,17 +2494,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet73 @@ -2514,6 +2514,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2523,17 +2526,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet74 @@ -2546,6 +2546,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2555,17 +2558,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet75 @@ -2578,6 +2578,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2587,17 +2590,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet76 @@ -2610,6 +2610,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2619,17 +2622,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet77 @@ -2642,6 +2642,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2651,17 +2654,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet78 @@ -2674,6 +2674,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2683,17 +2686,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet79 @@ -2706,6 +2706,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2715,17 +2718,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet80 @@ -2738,6 +2738,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2747,17 +2750,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet81 @@ -2770,6 +2770,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2779,17 +2782,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet82 @@ -2802,6 +2802,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2811,17 +2814,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet83 @@ -2834,6 +2834,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2843,17 +2846,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet84 @@ -2866,6 +2866,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2875,17 +2878,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet85 @@ -2898,6 +2898,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2907,17 +2910,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet86 @@ -2930,6 +2930,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2939,17 +2942,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet87 @@ -2962,6 +2962,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2971,17 +2974,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet88 @@ -2994,6 +2994,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3003,17 +3006,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet89 @@ -3026,6 +3026,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3035,17 +3038,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet90 @@ -3058,6 +3058,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3067,17 +3070,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet91 @@ -3090,6 +3090,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3099,17 +3102,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet92 @@ -3122,6 +3122,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3131,17 +3134,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet93 @@ -3154,6 +3154,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3163,17 +3166,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet94 @@ -3186,6 +3186,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3195,17 +3198,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet95 @@ -3218,6 +3218,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3227,17 +3230,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet96 @@ -3250,6 +3250,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3259,17 +3262,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled mlag_configuration: diff --git a/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3B.yml b/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3B.yml index 8ecdb46e0f6..f58464881c4 100644 --- a/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3B.yml +++ b/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3B.yml @@ -210,6 +210,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -219,17 +222,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet2 @@ -242,6 +242,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -251,17 +254,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3 @@ -274,6 +274,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -283,17 +286,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4 @@ -306,6 +306,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -315,17 +318,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5 @@ -338,6 +338,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -347,17 +350,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6 @@ -370,6 +370,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -379,17 +382,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7 @@ -402,6 +402,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -411,17 +414,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet8 @@ -434,6 +434,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -443,17 +446,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet9 @@ -466,6 +466,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -475,17 +478,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet10 @@ -498,6 +498,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -507,17 +510,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet11 @@ -530,6 +530,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -539,17 +542,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet12 @@ -562,6 +562,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -571,17 +574,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet13 @@ -594,6 +594,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -603,17 +606,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet14 @@ -626,6 +626,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -635,17 +638,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet15 @@ -658,6 +658,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -667,17 +670,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet16 @@ -690,6 +690,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -699,17 +702,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet17 @@ -722,6 +722,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -731,17 +734,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet18 @@ -754,6 +754,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -763,17 +766,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet19 @@ -786,6 +786,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -795,17 +798,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet20 @@ -818,6 +818,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -827,17 +830,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet21 @@ -850,6 +850,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -859,17 +862,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet22 @@ -882,6 +882,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -891,17 +894,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet23 @@ -914,6 +914,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -923,17 +926,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet24 @@ -946,6 +946,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -955,17 +958,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet25 @@ -978,6 +978,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -987,17 +990,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet26 @@ -1010,6 +1010,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1019,17 +1022,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet27 @@ -1042,6 +1042,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1051,17 +1054,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet28 @@ -1074,6 +1074,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1083,17 +1086,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet29 @@ -1106,6 +1106,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1115,17 +1118,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet30 @@ -1138,6 +1138,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1147,17 +1150,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet31 @@ -1170,6 +1170,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1179,17 +1182,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet32 @@ -1202,6 +1202,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1211,17 +1214,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet33 @@ -1234,6 +1234,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1243,17 +1246,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet34 @@ -1266,6 +1266,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1275,17 +1278,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet35 @@ -1298,6 +1298,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1307,17 +1310,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet36 @@ -1330,6 +1330,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1339,17 +1342,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet37 @@ -1362,6 +1362,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1371,17 +1374,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet38 @@ -1394,6 +1394,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1403,17 +1406,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet39 @@ -1426,6 +1426,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1435,17 +1438,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet40 @@ -1458,6 +1458,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1467,17 +1470,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet41 @@ -1490,6 +1490,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1499,17 +1502,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet42 @@ -1522,6 +1522,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1531,17 +1534,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet43 @@ -1554,6 +1554,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1563,17 +1566,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet44 @@ -1586,6 +1586,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1595,17 +1598,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet45 @@ -1618,6 +1618,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1627,17 +1630,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet46 @@ -1650,6 +1650,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1659,17 +1662,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet47 @@ -1682,6 +1682,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1691,17 +1694,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet48 @@ -1714,6 +1714,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1723,17 +1726,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet49 @@ -1746,6 +1746,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1755,17 +1758,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet50 @@ -1778,6 +1778,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1787,17 +1790,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet51 @@ -1810,6 +1810,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1819,17 +1822,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet52 @@ -1842,6 +1842,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1851,17 +1854,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet53 @@ -1874,6 +1874,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1883,17 +1886,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet54 @@ -1906,6 +1906,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1915,17 +1918,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet55 @@ -1938,6 +1938,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1947,17 +1950,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet56 @@ -1970,6 +1970,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1979,17 +1982,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet57 @@ -2002,6 +2002,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2011,17 +2014,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet58 @@ -2034,6 +2034,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2043,17 +2046,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet59 @@ -2066,6 +2066,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2075,17 +2078,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet60 @@ -2098,6 +2098,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2107,17 +2110,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet61 @@ -2130,6 +2130,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2139,17 +2142,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet62 @@ -2162,6 +2162,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2171,17 +2174,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet63 @@ -2194,6 +2194,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2203,17 +2206,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet64 @@ -2226,6 +2226,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2235,17 +2238,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet65 @@ -2258,6 +2258,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2267,17 +2270,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet66 @@ -2290,6 +2290,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2299,17 +2302,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet67 @@ -2322,6 +2322,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2331,17 +2334,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet68 @@ -2354,6 +2354,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2363,17 +2366,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet69 @@ -2386,6 +2386,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2395,17 +2398,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet70 @@ -2418,6 +2418,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2427,17 +2430,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet71 @@ -2450,6 +2450,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2459,17 +2462,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet72 @@ -2482,6 +2482,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2491,17 +2494,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet73 @@ -2514,6 +2514,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2523,17 +2526,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet74 @@ -2546,6 +2546,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2555,17 +2558,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet75 @@ -2578,6 +2578,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2587,17 +2590,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet76 @@ -2610,6 +2610,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2619,17 +2622,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet77 @@ -2642,6 +2642,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2651,17 +2654,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet78 @@ -2674,6 +2674,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2683,17 +2686,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet79 @@ -2706,6 +2706,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2715,17 +2718,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet80 @@ -2738,6 +2738,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2747,17 +2750,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet81 @@ -2770,6 +2770,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2779,17 +2782,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet82 @@ -2802,6 +2802,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2811,17 +2814,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet83 @@ -2834,6 +2834,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2843,17 +2846,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet84 @@ -2866,6 +2866,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2875,17 +2878,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet85 @@ -2898,6 +2898,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2907,17 +2910,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet86 @@ -2930,6 +2930,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2939,17 +2942,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet87 @@ -2962,6 +2962,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2971,17 +2974,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet88 @@ -2994,6 +2994,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3003,17 +3006,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet89 @@ -3026,6 +3026,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3035,17 +3038,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet90 @@ -3058,6 +3058,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3067,17 +3070,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet91 @@ -3090,6 +3090,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3099,17 +3102,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet92 @@ -3122,6 +3122,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3131,17 +3134,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet93 @@ -3154,6 +3154,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3163,17 +3166,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet94 @@ -3186,6 +3186,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3195,17 +3198,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet95 @@ -3218,6 +3218,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3227,17 +3230,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet96 @@ -3250,6 +3250,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3259,17 +3262,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled mlag_configuration: diff --git a/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3C.yml b/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3C.yml index 13757d269ee..442e0091b9a 100644 --- a/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3C.yml +++ b/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3C.yml @@ -87,6 +87,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -96,17 +99,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet2 @@ -119,6 +119,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -128,17 +131,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3 @@ -151,6 +151,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -160,17 +163,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4 @@ -183,6 +183,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -192,17 +195,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5 @@ -215,6 +215,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -224,17 +227,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6 @@ -247,6 +247,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -256,17 +259,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7 @@ -279,6 +279,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -288,17 +291,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet8 @@ -311,6 +311,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -320,17 +323,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet9 @@ -343,6 +343,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -352,17 +355,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet10 @@ -375,6 +375,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -384,17 +387,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet11 @@ -407,6 +407,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -416,17 +419,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet12 @@ -439,6 +439,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -448,17 +451,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet13 @@ -471,6 +471,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -480,17 +483,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet14 @@ -503,6 +503,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -512,17 +515,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet15 @@ -535,6 +535,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -544,17 +547,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet16 @@ -567,6 +567,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -576,17 +579,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet17 @@ -599,6 +599,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -608,17 +611,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet18 @@ -631,6 +631,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -640,17 +643,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet19 @@ -663,6 +663,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -672,17 +675,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet20 @@ -695,6 +695,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -704,17 +707,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet21 @@ -727,6 +727,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -736,17 +739,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet22 @@ -759,6 +759,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -768,17 +771,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet23 @@ -791,6 +791,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -800,17 +803,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet24 @@ -823,6 +823,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -832,17 +835,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet25 @@ -855,6 +855,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -864,17 +867,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet26 @@ -887,6 +887,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -896,17 +899,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet27 @@ -919,6 +919,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -928,17 +931,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet28 @@ -951,6 +951,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -960,17 +963,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet29 @@ -983,6 +983,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -992,17 +995,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet30 @@ -1015,6 +1015,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1024,17 +1027,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet31 @@ -1047,6 +1047,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1056,17 +1059,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet32 @@ -1079,6 +1079,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1088,17 +1091,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet33 @@ -1111,6 +1111,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1120,17 +1123,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet34 @@ -1143,6 +1143,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1152,17 +1155,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet35 @@ -1175,6 +1175,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1184,17 +1187,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet36 @@ -1207,6 +1207,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1216,17 +1219,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet37 @@ -1239,6 +1239,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1248,17 +1251,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet38 @@ -1271,6 +1271,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1280,17 +1283,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet39 @@ -1303,6 +1303,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1312,17 +1315,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet40 @@ -1335,6 +1335,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1344,17 +1347,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet41 @@ -1367,6 +1367,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1376,17 +1379,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet42 @@ -1399,6 +1399,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1408,17 +1411,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet43 @@ -1431,6 +1431,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1440,17 +1443,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet44 @@ -1463,6 +1463,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1472,17 +1475,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet45 @@ -1495,6 +1495,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1504,17 +1507,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet46 @@ -1527,6 +1527,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1536,17 +1539,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet47 @@ -1559,6 +1559,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1568,17 +1571,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet48 @@ -1591,6 +1591,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1600,17 +1603,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet49 @@ -1623,6 +1623,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1632,17 +1635,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet50 @@ -1655,6 +1655,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1664,17 +1667,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet51 @@ -1687,6 +1687,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1696,17 +1699,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet52 @@ -1719,6 +1719,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1728,17 +1731,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet53 @@ -1751,6 +1751,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1760,17 +1763,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet54 @@ -1783,6 +1783,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1792,17 +1795,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet55 @@ -1815,6 +1815,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1824,17 +1827,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet56 @@ -1847,6 +1847,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1856,17 +1859,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet57 @@ -1879,6 +1879,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1888,17 +1891,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet58 @@ -1911,6 +1911,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1920,17 +1923,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet59 @@ -1943,6 +1943,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1952,17 +1955,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet60 @@ -1975,6 +1975,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1984,17 +1987,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet61 @@ -2007,6 +2007,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2016,17 +2019,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet62 @@ -2039,6 +2039,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2048,17 +2051,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet63 @@ -2071,6 +2071,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2080,17 +2083,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet64 @@ -2103,6 +2103,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2112,17 +2115,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet65 @@ -2135,6 +2135,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2144,17 +2147,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet66 @@ -2167,6 +2167,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2176,17 +2179,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet67 @@ -2199,6 +2199,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2208,17 +2211,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet68 @@ -2231,6 +2231,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2240,17 +2243,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet69 @@ -2263,6 +2263,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2272,17 +2275,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet70 @@ -2295,6 +2295,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2304,17 +2307,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet71 @@ -2327,6 +2327,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2336,17 +2339,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet72 @@ -2359,6 +2359,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2368,17 +2371,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet73 @@ -2391,6 +2391,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2400,17 +2403,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet74 @@ -2423,6 +2423,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2432,17 +2435,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet75 @@ -2455,6 +2455,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2464,17 +2467,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet76 @@ -2487,6 +2487,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2496,17 +2499,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet77 @@ -2519,6 +2519,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2528,17 +2531,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet78 @@ -2551,6 +2551,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2560,17 +2563,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet79 @@ -2583,6 +2583,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2592,17 +2595,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet80 @@ -2615,6 +2615,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2624,17 +2627,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet81 @@ -2647,6 +2647,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2656,17 +2659,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet82 @@ -2679,6 +2679,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2688,17 +2691,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet83 @@ -2711,6 +2711,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2720,17 +2723,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet84 @@ -2743,6 +2743,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2752,17 +2755,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet85 @@ -2775,6 +2775,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2784,17 +2787,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet86 @@ -2807,6 +2807,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2816,17 +2819,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet87 @@ -2839,6 +2839,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2848,17 +2851,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet88 @@ -2871,6 +2871,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2880,17 +2883,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet89 @@ -2903,6 +2903,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2912,17 +2915,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet90 @@ -2935,6 +2935,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2944,17 +2947,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet91 @@ -2967,6 +2967,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2976,17 +2979,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet92 @@ -2999,6 +2999,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3008,17 +3011,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet93 @@ -3031,6 +3031,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3040,17 +3043,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet94 @@ -3063,6 +3063,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3072,17 +3075,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet95 @@ -3095,6 +3095,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3104,17 +3107,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet96 @@ -3127,6 +3127,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3136,17 +3139,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled port_channel_interfaces: diff --git a/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3D.yml b/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3D.yml index bcddc613dd9..b059f249a41 100644 --- a/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3D.yml +++ b/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3D.yml @@ -87,6 +87,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -96,17 +99,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet2 @@ -119,6 +119,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -128,17 +131,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3 @@ -151,6 +151,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -160,17 +163,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4 @@ -183,6 +183,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -192,17 +195,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5 @@ -215,6 +215,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -224,17 +227,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6 @@ -247,6 +247,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -256,17 +259,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7 @@ -279,6 +279,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -288,17 +291,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet8 @@ -311,6 +311,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -320,17 +323,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet9 @@ -343,6 +343,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -352,17 +355,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet10 @@ -375,6 +375,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -384,17 +387,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet11 @@ -407,6 +407,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -416,17 +419,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet12 @@ -439,6 +439,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -448,17 +451,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet13 @@ -471,6 +471,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -480,17 +483,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet14 @@ -503,6 +503,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -512,17 +515,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet15 @@ -535,6 +535,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -544,17 +547,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet16 @@ -567,6 +567,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -576,17 +579,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet17 @@ -599,6 +599,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -608,17 +611,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet18 @@ -631,6 +631,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -640,17 +643,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet19 @@ -663,6 +663,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -672,17 +675,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet20 @@ -695,6 +695,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -704,17 +707,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet21 @@ -727,6 +727,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -736,17 +739,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet22 @@ -759,6 +759,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -768,17 +771,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet23 @@ -791,6 +791,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -800,17 +803,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet24 @@ -823,6 +823,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -832,17 +835,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet25 @@ -855,6 +855,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -864,17 +867,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet26 @@ -887,6 +887,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -896,17 +899,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet27 @@ -919,6 +919,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -928,17 +931,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet28 @@ -951,6 +951,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -960,17 +963,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet29 @@ -983,6 +983,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -992,17 +995,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet30 @@ -1015,6 +1015,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1024,17 +1027,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet31 @@ -1047,6 +1047,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1056,17 +1059,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet32 @@ -1079,6 +1079,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1088,17 +1091,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet33 @@ -1111,6 +1111,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1120,17 +1123,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet34 @@ -1143,6 +1143,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1152,17 +1155,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet35 @@ -1175,6 +1175,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1184,17 +1187,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet36 @@ -1207,6 +1207,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1216,17 +1219,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet37 @@ -1239,6 +1239,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1248,17 +1251,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet38 @@ -1271,6 +1271,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1280,17 +1283,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet39 @@ -1303,6 +1303,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1312,17 +1315,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet40 @@ -1335,6 +1335,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1344,17 +1347,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet41 @@ -1367,6 +1367,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1376,17 +1379,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet42 @@ -1399,6 +1399,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1408,17 +1411,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet43 @@ -1431,6 +1431,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1440,17 +1443,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet44 @@ -1463,6 +1463,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1472,17 +1475,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet45 @@ -1495,6 +1495,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1504,17 +1507,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet46 @@ -1527,6 +1527,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1536,17 +1539,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet47 @@ -1559,6 +1559,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1568,17 +1571,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet48 @@ -1591,6 +1591,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1600,17 +1603,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet49 @@ -1623,6 +1623,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1632,17 +1635,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet50 @@ -1655,6 +1655,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1664,17 +1667,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet51 @@ -1687,6 +1687,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1696,17 +1699,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet52 @@ -1719,6 +1719,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1728,17 +1731,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet53 @@ -1751,6 +1751,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1760,17 +1763,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet54 @@ -1783,6 +1783,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1792,17 +1795,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet55 @@ -1815,6 +1815,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1824,17 +1827,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet56 @@ -1847,6 +1847,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1856,17 +1859,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet57 @@ -1879,6 +1879,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1888,17 +1891,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet58 @@ -1911,6 +1911,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1920,17 +1923,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet59 @@ -1943,6 +1943,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1952,17 +1955,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet60 @@ -1975,6 +1975,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1984,17 +1987,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet61 @@ -2007,6 +2007,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2016,17 +2019,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet62 @@ -2039,6 +2039,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2048,17 +2051,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet63 @@ -2071,6 +2071,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2080,17 +2083,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet64 @@ -2103,6 +2103,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2112,17 +2115,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet65 @@ -2135,6 +2135,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2144,17 +2147,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet66 @@ -2167,6 +2167,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2176,17 +2179,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet67 @@ -2199,6 +2199,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2208,17 +2211,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet68 @@ -2231,6 +2231,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2240,17 +2243,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet69 @@ -2263,6 +2263,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2272,17 +2275,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet70 @@ -2295,6 +2295,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2304,17 +2307,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet71 @@ -2327,6 +2327,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2336,17 +2339,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet72 @@ -2359,6 +2359,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2368,17 +2371,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet73 @@ -2391,6 +2391,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2400,17 +2403,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet74 @@ -2423,6 +2423,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2432,17 +2435,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet75 @@ -2455,6 +2455,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2464,17 +2467,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet76 @@ -2487,6 +2487,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2496,17 +2499,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet77 @@ -2519,6 +2519,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2528,17 +2531,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet78 @@ -2551,6 +2551,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2560,17 +2563,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet79 @@ -2583,6 +2583,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2592,17 +2595,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet80 @@ -2615,6 +2615,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2624,17 +2627,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet81 @@ -2647,6 +2647,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2656,17 +2659,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet82 @@ -2679,6 +2679,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2688,17 +2691,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet83 @@ -2711,6 +2711,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2720,17 +2723,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet84 @@ -2743,6 +2743,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2752,17 +2755,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet85 @@ -2775,6 +2775,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2784,17 +2787,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet86 @@ -2807,6 +2807,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2816,17 +2819,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet87 @@ -2839,6 +2839,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2848,17 +2851,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet88 @@ -2871,6 +2871,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2880,17 +2883,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet89 @@ -2903,6 +2903,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2912,17 +2915,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet90 @@ -2935,6 +2935,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2944,17 +2947,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet91 @@ -2967,6 +2967,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2976,17 +2979,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet92 @@ -2999,6 +2999,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3008,17 +3011,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet93 @@ -3031,6 +3031,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3040,17 +3043,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet94 @@ -3063,6 +3063,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3072,17 +3075,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet95 @@ -3095,6 +3095,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3104,17 +3107,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet96 @@ -3127,6 +3127,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3136,17 +3139,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled port_channel_interfaces: diff --git a/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3E.yml b/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3E.yml index a595c6e20e7..0a49d505ff7 100644 --- a/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3E.yml +++ b/ansible_collections/arista/avd/examples/campus-fabric/intended/structured_configs/LEAF3E.yml @@ -87,6 +87,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -96,17 +99,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet2 @@ -119,6 +119,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -128,17 +131,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet3 @@ -151,6 +151,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -160,17 +163,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet4 @@ -183,6 +183,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -192,17 +195,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet5 @@ -215,6 +215,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -224,17 +227,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet6 @@ -247,6 +247,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -256,17 +259,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet7 @@ -279,6 +279,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -288,17 +291,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet8 @@ -311,6 +311,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -320,17 +323,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet9 @@ -343,6 +343,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -352,17 +355,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet10 @@ -375,6 +375,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -384,17 +387,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet11 @@ -407,6 +407,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -416,17 +419,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet12 @@ -439,6 +439,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -448,17 +451,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet13 @@ -471,6 +471,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -480,17 +483,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet14 @@ -503,6 +503,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -512,17 +515,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet15 @@ -535,6 +535,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -544,17 +547,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet16 @@ -567,6 +567,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -576,17 +579,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet17 @@ -599,6 +599,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -608,17 +611,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet18 @@ -631,6 +631,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -640,17 +643,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet19 @@ -663,6 +663,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -672,17 +675,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet20 @@ -695,6 +695,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -704,17 +707,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet21 @@ -727,6 +727,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -736,17 +739,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet22 @@ -759,6 +759,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -768,17 +771,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet23 @@ -791,6 +791,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -800,17 +803,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet24 @@ -823,6 +823,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -832,17 +835,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet25 @@ -855,6 +855,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -864,17 +867,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet26 @@ -887,6 +887,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -896,17 +899,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet27 @@ -919,6 +919,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -928,17 +931,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet28 @@ -951,6 +951,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -960,17 +963,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet29 @@ -983,6 +983,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -992,17 +995,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet30 @@ -1015,6 +1015,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1024,17 +1027,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet31 @@ -1047,6 +1047,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1056,17 +1059,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet32 @@ -1079,6 +1079,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1088,17 +1091,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet33 @@ -1111,6 +1111,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1120,17 +1123,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet34 @@ -1143,6 +1143,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1152,17 +1155,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet35 @@ -1175,6 +1175,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1184,17 +1187,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet36 @@ -1207,6 +1207,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1216,17 +1219,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet37 @@ -1239,6 +1239,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1248,17 +1251,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet38 @@ -1271,6 +1271,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1280,17 +1283,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet39 @@ -1303,6 +1303,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1312,17 +1315,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet40 @@ -1335,6 +1335,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1344,17 +1347,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet41 @@ -1367,6 +1367,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1376,17 +1379,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet42 @@ -1399,6 +1399,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1408,17 +1411,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet43 @@ -1431,6 +1431,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1440,17 +1443,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet44 @@ -1463,6 +1463,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1472,17 +1475,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet45 @@ -1495,6 +1495,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1504,17 +1507,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet46 @@ -1527,6 +1527,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1536,17 +1539,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet47 @@ -1559,6 +1559,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1568,17 +1571,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet48 @@ -1591,6 +1591,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1600,17 +1603,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet49 @@ -1623,6 +1623,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1632,17 +1635,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet50 @@ -1655,6 +1655,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1664,17 +1667,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet51 @@ -1687,6 +1687,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1696,17 +1699,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet52 @@ -1719,6 +1719,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1728,17 +1731,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet53 @@ -1751,6 +1751,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1760,17 +1763,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet54 @@ -1783,6 +1783,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1792,17 +1795,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet55 @@ -1815,6 +1815,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1824,17 +1827,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet56 @@ -1847,6 +1847,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1856,17 +1859,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet57 @@ -1879,6 +1879,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1888,17 +1891,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet58 @@ -1911,6 +1911,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1920,17 +1923,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet59 @@ -1943,6 +1943,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1952,17 +1955,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet60 @@ -1975,6 +1975,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -1984,17 +1987,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet61 @@ -2007,6 +2007,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2016,17 +2019,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet62 @@ -2039,6 +2039,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2048,17 +2051,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet63 @@ -2071,6 +2071,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2080,17 +2083,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet64 @@ -2103,6 +2103,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2112,17 +2115,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet65 @@ -2135,6 +2135,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2144,17 +2147,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet66 @@ -2167,6 +2167,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2176,17 +2179,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet67 @@ -2199,6 +2199,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2208,17 +2211,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet68 @@ -2231,6 +2231,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2240,17 +2243,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet69 @@ -2263,6 +2263,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2272,17 +2275,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet70 @@ -2295,6 +2295,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2304,17 +2307,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet71 @@ -2327,6 +2327,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2336,17 +2339,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet72 @@ -2359,6 +2359,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2368,17 +2371,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet73 @@ -2391,6 +2391,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2400,17 +2403,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet74 @@ -2423,6 +2423,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2432,17 +2435,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet75 @@ -2455,6 +2455,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2464,17 +2467,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet76 @@ -2487,6 +2487,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2496,17 +2499,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet77 @@ -2519,6 +2519,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2528,17 +2531,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet78 @@ -2551,6 +2551,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2560,17 +2563,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet79 @@ -2583,6 +2583,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2592,17 +2595,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet80 @@ -2615,6 +2615,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2624,17 +2627,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet81 @@ -2647,6 +2647,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2656,17 +2659,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet82 @@ -2679,6 +2679,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2688,17 +2691,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet83 @@ -2711,6 +2711,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2720,17 +2723,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet84 @@ -2743,6 +2743,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2752,17 +2755,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet85 @@ -2775,6 +2775,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2784,17 +2787,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet86 @@ -2807,6 +2807,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2816,17 +2819,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet87 @@ -2839,6 +2839,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2848,17 +2851,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet88 @@ -2871,6 +2871,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2880,17 +2883,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet89 @@ -2903,6 +2903,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2912,17 +2915,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet90 @@ -2935,6 +2935,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2944,17 +2947,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet91 @@ -2967,6 +2967,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -2976,17 +2979,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet92 @@ -2999,6 +2999,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3008,17 +3011,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet93 @@ -3031,6 +3031,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3040,17 +3043,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet94 @@ -3063,6 +3063,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3072,17 +3075,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet95 @@ -3095,6 +3095,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3104,17 +3107,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled - name: Ethernet96 @@ -3127,6 +3127,9 @@ ethernet_interfaces: reauthentication: true pae: mode: authenticator + authentication_failure: + action: allow + allow_vlan: 330 host_mode: mode: multi-host multi_host_authenticated: true @@ -3136,17 +3139,14 @@ ethernet_interfaces: reauth_period: server tx_period: 3 reauthorization_request_limit: 3 - authentication_failure: - action: allow - allow_vlan: 330 switchport: enabled: true mode: trunk phone trunk: native_vlan: 310 phone: - trunk: untagged vlan: 320 + trunk: untagged spanning_tree_portfast: edge spanning_tree_bpduguard: enabled port_channel_interfaces: diff --git a/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/inet-cloud.yml b/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/inet-cloud.yml index fc539f056d1..ff44c321f9d 100644 --- a/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/inet-cloud.yml +++ b/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/inet-cloud.yml @@ -23,8 +23,8 @@ router_bgp: activate: true neighbors: - ip_address: 100.64.21.2 - remote_as: '65000' peer_group: IPv4-UNDERLAY-PEERS + remote_as: '65000' default_originate: enabled: true always: true diff --git a/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/pf1.yml b/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/pf1.yml index 152b367207e..67f896e0e9b 100644 --- a/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/pf1.yml +++ b/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/pf1.yml @@ -236,32 +236,32 @@ ip_access_lists: entries: - sequence: 1 remark: 'Not for PRODUCTION: This ACL is built this way because the lab has an out-of-band interface' - - sequence: 10 + - source: any + destination: 100.64.100.2 + sequence: 10 action: permit protocol: udp - source: any - destination: 100.64.100.2 destination_ports_match: eq destination_ports: - isakmp - non500-isakmp - - sequence: 20 + - source: any + destination: 100.64.100.2 + sequence: 20 action: permit protocol: udp - source: any - destination: 100.64.100.2 destination_ports_match: eq destination_ports: - '3478' - - sequence: 30 + - source: any + destination: 100.64.100.2 + sequence: 30 action: permit protocol: icmp - source: any - destination: 100.64.100.2 - - action: deny - protocol: ip - source: any + - source: any destination: any + action: deny + protocol: ip ip_extcommunity_lists: - name: ECL-EVPN-SOO entries: @@ -479,8 +479,8 @@ application_traffic_recognition: protocols: - tcp - udp - tcp_dest_port_set_name: VIDEO-PORTS udp_dest_port_set_name: VIDEO-PORTS + tcp_dest_port_set_name: VIDEO-PORTS - name: VOICE-APP protocols: - tcp diff --git a/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/pf2.yml b/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/pf2.yml index 286d28beaf0..63fa40ce06f 100644 --- a/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/pf2.yml +++ b/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/pf2.yml @@ -236,32 +236,32 @@ ip_access_lists: entries: - sequence: 1 remark: 'Not for PRODUCTION: This ACL is built this way because the lab has an out-of-band interface' - - sequence: 10 + - source: any + destination: 100.64.200.2 + sequence: 10 action: permit protocol: udp - source: any - destination: 100.64.200.2 destination_ports_match: eq destination_ports: - isakmp - non500-isakmp - - sequence: 20 + - source: any + destination: 100.64.200.2 + sequence: 20 action: permit protocol: udp - source: any - destination: 100.64.200.2 destination_ports_match: eq destination_ports: - '3478' - - sequence: 30 + - source: any + destination: 100.64.200.2 + sequence: 30 action: permit protocol: icmp - source: any - destination: 100.64.200.2 - - action: deny - protocol: ip - source: any + - source: any destination: any + action: deny + protocol: ip ip_extcommunity_lists: - name: ECL-EVPN-SOO entries: @@ -479,8 +479,8 @@ application_traffic_recognition: protocols: - tcp - udp - tcp_dest_port_set_name: VIDEO-PORTS udp_dest_port_set_name: VIDEO-PORTS + tcp_dest_port_set_name: VIDEO-PORTS - name: VOICE-APP protocols: - tcp diff --git a/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site1-wan1.yml b/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site1-wan1.yml index 29cfd806663..26ebe38fe11 100644 --- a/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site1-wan1.yml +++ b/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site1-wan1.yml @@ -458,24 +458,24 @@ ip_access_lists: entries: - sequence: 1 remark: 'Not for PRODUCTION: This ACL is built this way because the lab has an out-of-band interface' - - sequence: 10 + - source: any + destination: 100.64.10.2 + sequence: 10 action: permit protocol: udp - source: any - destination: 100.64.10.2 destination_ports_match: eq destination_ports: - isakmp - non500-isakmp - - sequence: 30 + - source: any + destination: 100.64.10.2 + sequence: 30 action: permit protocol: icmp - source: any - destination: 100.64.10.2 - - action: deny - protocol: ip - source: any + - source: any destination: any + action: deny + protocol: ip ip_extcommunity_lists: - name: ECL-EVPN-SOO entries: @@ -758,8 +758,8 @@ application_traffic_recognition: protocols: - tcp - udp - tcp_dest_port_set_name: VIDEO-PORTS udp_dest_port_set_name: VIDEO-PORTS + tcp_dest_port_set_name: VIDEO-PORTS - name: VOICE-APP protocols: - tcp diff --git a/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site1-wan2.yml b/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site1-wan2.yml index 470aeee3f7c..6cd61b9e2be 100644 --- a/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site1-wan2.yml +++ b/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site1-wan2.yml @@ -459,24 +459,24 @@ ip_access_lists: entries: - sequence: 1 remark: 'Not for PRODUCTION: This ACL is built this way because the lab has an out-of-band interface' - - sequence: 10 + - source: any + destination: 100.64.11.2 + sequence: 10 action: permit protocol: udp - source: any - destination: 100.64.11.2 destination_ports_match: eq destination_ports: - isakmp - non500-isakmp - - sequence: 30 + - source: any + destination: 100.64.11.2 + sequence: 30 action: permit protocol: icmp - source: any - destination: 100.64.11.2 - - action: deny - protocol: ip - source: any + - source: any destination: any + action: deny + protocol: ip ip_extcommunity_lists: - name: ECL-EVPN-SOO entries: @@ -759,8 +759,8 @@ application_traffic_recognition: protocols: - tcp - udp - tcp_dest_port_set_name: VIDEO-PORTS udp_dest_port_set_name: VIDEO-PORTS + tcp_dest_port_set_name: VIDEO-PORTS - name: VOICE-APP protocols: - tcp diff --git a/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site2-wan1.yml b/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site2-wan1.yml index e496e45d600..fecdf1bbf60 100644 --- a/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site2-wan1.yml +++ b/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site2-wan1.yml @@ -611,8 +611,8 @@ application_traffic_recognition: protocols: - tcp - udp - tcp_dest_port_set_name: VIDEO-PORTS udp_dest_port_set_name: VIDEO-PORTS + tcp_dest_port_set_name: VIDEO-PORTS - name: VOICE-APP protocols: - tcp diff --git a/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site2-wan2.yml b/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site2-wan2.yml index 61ff8a62567..b95710ba067 100644 --- a/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site2-wan2.yml +++ b/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site2-wan2.yml @@ -393,32 +393,32 @@ ip_access_lists: entries: - sequence: 1 remark: 'Not for PRODUCTION: This ACL is built this way because the lab has an out-of-band interface' - - sequence: 10 + - source: any + destination: 100.64.21.2 + sequence: 10 action: permit protocol: udp - source: any - destination: 100.64.21.2 destination_ports_match: eq destination_ports: - isakmp - non500-isakmp - - sequence: 20 + - source: any + destination: 100.64.21.2 + sequence: 20 action: permit protocol: tcp - source: any - destination: 100.64.21.2 destination_ports_match: eq destination_ports: - bgp - - sequence: 30 + - source: any + destination: 100.64.21.2 + sequence: 30 action: permit protocol: icmp - source: any - destination: 100.64.21.2 - - action: deny - protocol: ip - source: any + - source: any destination: any + action: deny + protocol: ip ip_extcommunity_lists: - name: ECL-EVPN-SOO entries: @@ -664,8 +664,8 @@ application_traffic_recognition: protocols: - tcp - udp - tcp_dest_port_set_name: VIDEO-PORTS udp_dest_port_set_name: VIDEO-PORTS + tcp_dest_port_set_name: VIDEO-PORTS - name: VOICE-APP protocols: - tcp diff --git a/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site3-wan1.yml b/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site3-wan1.yml index c3ea79c5801..a5c8da00bd0 100644 --- a/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site3-wan1.yml +++ b/ansible_collections/arista/avd/examples/cv-pathfinder/intended/structured_configs/site3-wan1.yml @@ -276,24 +276,24 @@ ip_access_lists: entries: - sequence: 1 remark: 'Not for PRODUCTION: This ACL is built this way because the lab has an out-of-band interface' - - sequence: 10 + - source: any + destination: 100.64.30.2 + sequence: 10 action: permit protocol: udp - source: any - destination: 100.64.30.2 destination_ports_match: eq destination_ports: - isakmp - non500-isakmp - - sequence: 30 + - source: any + destination: 100.64.30.2 + sequence: 30 action: permit protocol: icmp - source: any - destination: 100.64.30.2 - - action: deny - protocol: ip - source: any + - source: any destination: any + action: deny + protocol: ip ip_extcommunity_lists: - name: ECL-EVPN-SOO entries: @@ -506,8 +506,8 @@ application_traffic_recognition: protocols: - tcp - udp - tcp_dest_port_set_name: VIDEO-PORTS udp_dest_port_set_name: VIDEO-PORTS + tcp_dest_port_set_name: VIDEO-PORTS - name: VOICE-APP protocols: - tcp diff --git a/ansible_collections/arista/avd/examples/isis-ldp-ipvpn/intended/structured_configs/pe1.yml b/ansible_collections/arista/avd/examples/isis-ldp-ipvpn/intended/structured_configs/pe1.yml index 55c34d4abf3..b7319c94f93 100644 --- a/ansible_collections/arista/avd/examples/isis-ldp-ipvpn/intended/structured_configs/pe1.yml +++ b/ansible_collections/arista/avd/examples/isis-ldp-ipvpn/intended/structured_configs/pe1.yml @@ -247,9 +247,9 @@ router_ospf: - id: 10 vrf: C1_VRF1 passive_interface_default: true + router_id: 10.255.1.1 no_passive_interfaces: - Ethernet3.10 - router_id: 10.255.1.1 redistribute: bgp: enabled: true diff --git a/ansible_collections/arista/avd/examples/isis-ldp-ipvpn/intended/structured_configs/pe2.yml b/ansible_collections/arista/avd/examples/isis-ldp-ipvpn/intended/structured_configs/pe2.yml index 25f1e0a874d..dacadc42e05 100644 --- a/ansible_collections/arista/avd/examples/isis-ldp-ipvpn/intended/structured_configs/pe2.yml +++ b/ansible_collections/arista/avd/examples/isis-ldp-ipvpn/intended/structured_configs/pe2.yml @@ -247,9 +247,9 @@ router_ospf: - id: 10 vrf: C1_VRF1 passive_interface_default: true + router_id: 10.255.1.2 no_passive_interfaces: - Ethernet4.10 - router_id: 10.255.1.2 redistribute: bgp: enabled: true diff --git a/ansible_collections/arista/avd/examples/isis-ldp-ipvpn/intended/structured_configs/pe3.yml b/ansible_collections/arista/avd/examples/isis-ldp-ipvpn/intended/structured_configs/pe3.yml index d175fb42cc2..b64d1eb47fe 100644 --- a/ansible_collections/arista/avd/examples/isis-ldp-ipvpn/intended/structured_configs/pe3.yml +++ b/ansible_collections/arista/avd/examples/isis-ldp-ipvpn/intended/structured_configs/pe3.yml @@ -242,9 +242,9 @@ router_ospf: - id: 10 vrf: C1_VRF1 passive_interface_default: true + router_id: 10.255.1.3 no_passive_interfaces: - Ethernet2 - router_id: 10.255.1.3 redistribute: bgp: enabled: true diff --git a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/intended/structured_configs/SITE1-LER1.yml b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/intended/structured_configs/SITE1-LER1.yml index a05916ece2e..569a677a113 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/intended/structured_configs/SITE1-LER1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/intended/structured_configs/SITE1-LER1.yml @@ -476,10 +476,10 @@ router_ospf: - id: 19 vrf: TENANT_B_INTRA passive_interface_default: true + router_id: 10.123.1.0 no_passive_interfaces: - Ethernet6.10 max_lsa: 10000 - router_id: 10.123.1.0 redistribute: bgp: enabled: true diff --git a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/intended/structured_configs/SITE1-LER2.yml b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/intended/structured_configs/SITE1-LER2.yml index 55f8241b0ba..841b33bb842 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/intended/structured_configs/SITE1-LER2.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/intended/structured_configs/SITE1-LER2.yml @@ -105,9 +105,9 @@ router_bgp: activate: true neighbors: - ip_address: 192.168.48.1 + remote_as: '65201' description: TENANT_B_CPE_SITE3 password: toZKiUFLVUTU4hdS5V8F4Q== - remote_as: '65201' updates: wait_install: true vlans: diff --git a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/intended/structured_configs/SITE2-LER1.yml b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/intended/structured_configs/SITE2-LER1.yml index 1d768ff6726..d5827d010aa 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/intended/structured_configs/SITE2-LER1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-mpls-isis-sr-ldp/intended/structured_configs/SITE2-LER1.yml @@ -101,9 +101,9 @@ router_bgp: activate: true neighbors: - ip_address: 192.168.48.3 + remote_as: '65202' description: TENANT_B_CPE_SITE5 password: OajzUG59/YF0NkgvOQyRnQ== - remote_as: '65202' updates: wait_install: true vlans: @@ -592,10 +592,10 @@ router_ospf: - id: 99 vrf: TENANT_B_WAN passive_interface_default: true + router_id: 192.168.48.4 no_passive_interfaces: - Ethernet6.100 max_lsa: 10000 - router_id: 192.168.48.4 redistribute: bgp: enabled: true diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-L2LEAF1A.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-L2LEAF1A.yml index 11700c4955b..00fd42381d4 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-L2LEAF1A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-L2LEAF1A.yml @@ -27,8 +27,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-L2LEAF2A.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-L2LEAF2A.yml index 960929006db..b5cb7d0856b 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-L2LEAF2A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-L2LEAF2A.yml @@ -28,8 +28,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-L2LEAF2B.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-L2LEAF2B.yml index 2dbc8e2ef04..d28ee65c325 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-L2LEAF2B.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-L2LEAF2B.yml @@ -28,8 +28,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-LEAF1A.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-LEAF1A.yml index 9c9713f89bb..ac1e286ee47 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-LEAF1A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-LEAF1A.yml @@ -125,8 +125,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-LEAF2B.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-LEAF2B.yml index f26c99dc6ab..e7b55cb73e2 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-LEAF2B.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-LEAF2B.yml @@ -330,8 +330,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-SPINE1.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-SPINE1.yml index f8a77461ccb..533eac9b64a 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-SPINE1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-SPINE1.yml @@ -146,8 +146,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-SPINE2.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-SPINE2.yml index 25f6f76acec..3d8e5de8649 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-SPINE2.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD1-SPINE2.yml @@ -86,8 +86,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD2-LEAF1A.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD2-LEAF1A.yml index 3bf70a5f405..b88f2869dd7 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD2-LEAF1A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD2-LEAF1A.yml @@ -240,8 +240,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD2-SPINE1.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD2-SPINE1.yml index 99fac07d4e4..7f51d23d5a7 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD2-SPINE1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD2-SPINE1.yml @@ -103,8 +103,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD2-SPINE2.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD2-SPINE2.yml index 45ed1842ff8..a62e1233544 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD2-SPINE2.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-POD2-SPINE2.yml @@ -99,8 +99,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-RS1.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-RS1.yml index c17403185e0..222c5c9f0e2 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-RS1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-RS1.yml @@ -124,8 +124,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-RS2.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-RS2.yml index 784974d7cae..d3169fe1001 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-RS2.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-RS2.yml @@ -114,8 +114,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-SUPER-SPINE1.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-SUPER-SPINE1.yml index 159327fc021..4a1e427bae6 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-SUPER-SPINE1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-SUPER-SPINE1.yml @@ -83,8 +83,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-SUPER-SPINE2.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-SUPER-SPINE2.yml index 5003fb56e64..dc9e12c6343 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-SUPER-SPINE2.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1-SUPER-SPINE2.yml @@ -82,8 +82,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1.POD1.LEAF2A.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1.POD1.LEAF2A.yml index 81d1c49d535..89de4f7ba60 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1.POD1.LEAF2A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC1.POD1.LEAF2A.yml @@ -298,8 +298,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-L2LEAF1A.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-L2LEAF1A.yml index 8526d3aa486..ecd7da5f31f 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-L2LEAF1A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-L2LEAF1A.yml @@ -27,8 +27,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-L2LEAF2A.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-L2LEAF2A.yml index 9aa8789ed94..b95c098c919 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-L2LEAF2A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-L2LEAF2A.yml @@ -27,8 +27,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-LEAF1A.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-LEAF1A.yml index 48c8d5077ea..ccd6017d426 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-LEAF1A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-LEAF1A.yml @@ -187,8 +187,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-LEAF2A.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-LEAF2A.yml index 3d7cc4bd85d..6591e25ff08 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-LEAF2A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-LEAF2A.yml @@ -85,8 +85,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-SPINE1.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-SPINE1.yml index c0b3ce06ba9..1515112b1f9 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-SPINE1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-SPINE1.yml @@ -115,8 +115,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-SPINE2.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-SPINE2.yml index c0b79d60b56..41e5c6b56db 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-SPINE2.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-POD1-SPINE2.yml @@ -76,8 +76,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-RS1.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-RS1.yml index c4bb7aac6d5..43382a0b3d1 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-RS1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-RS1.yml @@ -100,8 +100,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-RS2.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-RS2.yml index 259aa6c0367..c6d07a51ac9 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-RS2.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-RS2.yml @@ -60,8 +60,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-SUPER-SPINE1.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-SUPER-SPINE1.yml index 8a249940d24..24fff311dbf 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-SUPER-SPINE1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-SUPER-SPINE1.yml @@ -126,8 +126,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-SUPER-SPINE2.yml b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-SUPER-SPINE2.yml index 8523190701e..8cd0c2534c7 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-SUPER-SPINE2.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs-twodc-5stage-clos/intended/structured_configs/DC2-SUPER-SPINE2.yml @@ -65,8 +65,8 @@ local_users: - name: admin privilege: 15 role: network-admin - no_password: true sha512_password: $6$eJ5TvI8oru5i9e8G$R1X/SbtGTk9xoEHEBQASc7SC2nHYmi.crVgp2pXuCXwxsXEA81e4E0cXgQ6kX08fIeQzauqhv2kS.RGJFCon5/ + no_password: true vrfs: - name: MGMT ip_routing: false 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_unit_tests/intended/configs/core-1-isis-sr-ldp.cfg b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/configs/core-1-isis-sr-ldp.cfg index 8c44ae989cd..614d56a116d 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/configs/core-1-isis-sr-ldp.cfg +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/configs/core-1-isis-sr-ldp.cfg @@ -186,6 +186,8 @@ interface Ethernet10 description P2P_LINK_TO_CORE-2-OSPF-LDP_Ethernet10 no shutdown mtu 1500 + l2 mtu 2222 + l2 mru 2222 speed forced 1000full no switchport ip address 100.64.48.12/31 diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/configs/core-2-ospf-ldp.cfg b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/configs/core-2-ospf-ldp.cfg index 1114402b5d6..42812ae570d 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/configs/core-2-ospf-ldp.cfg +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/configs/core-2-ospf-ldp.cfg @@ -144,6 +144,8 @@ interface Ethernet10 description P2P_LINK_TO_CORE-1-ISIS-SR-LDP_Ethernet10 no shutdown mtu 1500 + l2 mtu 2222 + l2 mru 2222 speed forced 1000full no switchport ip address 100.64.48.13/31 diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/configs/custom-structured-configuration.cfg b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/configs/custom-structured-configuration.cfg index 48d3269f0b6..af4faddd92a 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/configs/custom-structured-configuration.cfg +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/configs/custom-structured-configuration.cfg @@ -11,6 +11,7 @@ username super-shared-admin privilege 2 role network-admin secret sha512 $6$.zTj ! vlan internal order ascending range 1006 1199 ! +! transceiver qsfp default-mode 4x10G ! service routing protocols model multi-agent @@ -29,11 +30,7 @@ ip name-server vrf MGMT 192.168.42.50 vrf instance MGMT ! management api http-commands - protocol https no shutdown - ! - vrf MGMT - no shutdown no ip routing vrf MGMT ! end diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/7010TX-LEAF1.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/7010TX-LEAF1.yml index a38290de382..b7308aee46a 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/7010TX-LEAF1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/7010TX-LEAF1.yml @@ -74,7 +74,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.201.116/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/7010TX-LEAF2.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/7010TX-LEAF2.yml index 89b7e8a89d3..66da0a099c9 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/7010TX-LEAF2.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/7010TX-LEAF2.yml @@ -74,7 +74,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.201.117/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-BL1A.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-BL1A.yml index 2e040a703a6..bf34edaab87 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-BL1A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-BL1A.yml @@ -170,8 +170,8 @@ router_bgp: neighbors: - ip_address: 123.1.1.10 remote_as: '1234' - password: oBztv71m2uhR7hh58/OCNA== description: External IPv4 BGP peer + password: oBztv71m2uhR7hh58/OCNA== send_community: standard extended maximum_routes: 0 maximum_routes_warning_only: true @@ -180,22 +180,22 @@ router_bgp: route_map: RM-Tenant_A_WAN_Zone-123.1.1.10-SET-NEXT-HOP-OUT update_source: Loopback123 ebgp_multihop: 3 - route_map_in: RM-123-1-1-10-IN - shutdown: true route_map_out: RM-Tenant_A_WAN_Zone-123.1.1.10-SET-NEXT-HOP-OUT + route_map_in: RM-123-1-1-10-IN local_as: '123' + shutdown: true - ip_address: 123.1.1.11 remote_as: '65000.100' - password: oBztv71m2uhR7hh58/OCNA== description: External IPv4 BGP peer + password: oBztv71m2uhR7hh58/OCNA== send_community: standard extended maximum_routes: 0 default_originate: always: false update_source: Loopback123 ebgp_multihop: 3 - route_map_in: RM-123-1-1-11-IN route_map_out: RM-123-1-1-11-OUT + route_map_in: RM-123-1-1-11-IN local_as: '123' bfd: true - ip_address: fd5a:fe45:8831:06c5::a @@ -578,14 +578,14 @@ ethernet_interfaces: shutdown: false - name: Ethernet4000 description: My test - ip_address: 10.3.2.1/21 shutdown: false - switchport: - enabled: false mtu: 1500 + ip_address: 10.3.2.1/21 peer: MY-own-peer peer_interface: Ethernet123 peer_type: my_precious + switchport: + enabled: false loopback_interfaces: - name: Loopback0 description: MY_ROUTER_ID_LOOPBACK @@ -646,32 +646,32 @@ vlans: ip_access_lists: - name: TEST-IPV4-ACL-WITH-IP-FIELDS-IN_Ethernet12 entries: - - sequence: 15 + - source: any + destination: 10.10.40.10 + sequence: 15 action: deny protocol: ip - source: any - destination: 10.10.40.10 - name: TEST-IPV4-ACL-WITH-IP-FIELDS-IN_Ethernet13.10 entries: - - sequence: 15 + - source: any + destination: 10.10.40.20 + sequence: 15 action: deny protocol: ip - source: any - destination: 10.10.40.20 - name: TEST-IPV4-ACL-WITH-IP-FIELDS-OUT_Ethernet12 entries: - remark: Some remark will not require source and destination fields. - - action: permit - protocol: ip - source: 10.10.40.10 + - source: 10.10.40.10 destination: any + action: permit + protocol: ip - name: TEST-IPV4-ACL-WITH-IP-FIELDS-OUT_Ethernet13.10 entries: - remark: Some remark will not require source and destination fields. - - action: permit - protocol: ip - source: 10.10.40.20 + - source: 10.10.40.20 destination: any + action: permit + protocol: ip ip_igmp_snooping: globally_enabled: true ip_virtual_router_mac_address: 00:dc:00:00:00:0a diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-BL1B.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-BL1B.yml index 230c18c3c3a..76f7fe9657a 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-BL1B.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-BL1B.yml @@ -173,8 +173,8 @@ router_bgp: neighbors: - ip_address: 123.1.1.10 remote_as: '1234' - password: oBztv71m2uhR7hh58/OCNA== description: External IPv4 BGP peer + password: oBztv71m2uhR7hh58/OCNA== send_community: standard extended maximum_routes: 0 maximum_routes_warning_only: true @@ -183,22 +183,22 @@ router_bgp: route_map: RM-Tenant_A_WAN_Zone-123.1.1.10-SET-NEXT-HOP-OUT update_source: Loopback123 ebgp_multihop: 3 - route_map_in: RM-123-1-1-10-IN - shutdown: true route_map_out: RM-Tenant_A_WAN_Zone-123.1.1.10-SET-NEXT-HOP-OUT + route_map_in: RM-123-1-1-10-IN local_as: '123' + shutdown: true - ip_address: 123.1.1.11 remote_as: '65000.100' - password: oBztv71m2uhR7hh58/OCNA== description: External IPv4 BGP peer + password: oBztv71m2uhR7hh58/OCNA== send_community: standard extended maximum_routes: 0 default_originate: always: false update_source: Loopback123 ebgp_multihop: 3 - route_map_in: RM-123-1-1-11-IN route_map_out: RM-123-1-1-11-OUT + route_map_in: RM-123-1-1-11-IN local_as: '123' bfd: true - ip_address: fd5a:fe45:8831:06c5::a @@ -554,14 +554,14 @@ ethernet_interfaces: shutdown: false - name: Ethernet4000 description: My second test - ip_address: 10.1.2.3/12 shutdown: false - switchport: - enabled: false mtu: 1500 + ip_address: 10.1.2.3/12 peer: MY-own-peer peer_interface: Ethernet123 peer_type: my_precious + switchport: + enabled: false loopback_interfaces: - name: Loopback0 description: ROUTER_ID @@ -618,32 +618,32 @@ vlans: ip_access_lists: - name: TEST-IPV4-ACL-WITH-IP-FIELDS-IN_Ethernet12 entries: - - sequence: 15 + - source: any + destination: 10.10.50.10 + sequence: 15 action: deny protocol: ip - source: any - destination: 10.10.50.10 - name: TEST-IPV4-ACL-WITH-IP-FIELDS-IN_Ethernet13.10 entries: - - sequence: 15 + - source: any + destination: 10.10.50.20 + sequence: 15 action: deny protocol: ip - source: any - destination: 10.10.50.20 - name: TEST-IPV4-ACL-WITH-IP-FIELDS-OUT_Ethernet12 entries: - remark: Some remark will not require source and destination fields. - - action: permit - protocol: ip - source: 10.10.50.10 + - source: 10.10.50.10 destination: any + action: permit + protocol: ip - name: TEST-IPV4-ACL-WITH-IP-FIELDS-OUT_Ethernet13.10 entries: - remark: Some remark will not require source and destination fields. - - action: permit - protocol: ip - source: 10.10.50.20 + - source: 10.10.50.20 destination: any + action: permit + protocol: ip ip_igmp_snooping: globally_enabled: true ip_virtual_router_mac_address: 00:dc:00:00:00:0a @@ -692,10 +692,10 @@ router_ospf: - id: 14 vrf: Tenant_A_WAN_Zone passive_interface_default: true + router_id: 192.168.255.15 no_passive_interfaces: - Vlan150 max_lsa: 15000 - router_id: 192.168.255.15 redistribute: bgp: enabled: true diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-BL2A.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-BL2A.yml index 63f815026a2..7b993f9b932 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-BL2A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-BL2A.yml @@ -43,19 +43,19 @@ router_bgp: local_as: '65001' - name: Tenant_C_BGP_PEER_GROUP remote_as: '666' + local_as: '777' description: Tenant C peer group - send_community: all + update_source: lo0 + bfd: false + ebgp_multihop: 3 next_hop_self: true - maximum_routes: 1000 default_originate: enabled: true always: true - update_source: lo0 - bfd: false - ebgp_multihop: 3 - route_map_out: TEST_OUT + send_community: all + maximum_routes: 1000 route_map_in: TEST_IN - local_as: '777' + route_map_out: TEST_OUT - name: Tenant_C_BGP_PEER_GROUP2 remote_as: '667' description: Tenant C peer group2 diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-BL2B.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-BL2B.yml index 86f93838b74..527f458e95b 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-BL2B.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-BL2B.yml @@ -43,19 +43,19 @@ router_bgp: local_as: '65001' - name: Tenant_C_WAN_Zone_BGP_PEER_GROUP remote_as: '666' + local_as: '777' description: Tenant C VRF WAN Zone peer group - send_community: all + update_source: lo0 + bfd: false + ebgp_multihop: 3 next_hop_self: true - maximum_routes: 1000 default_originate: enabled: true always: true - update_source: lo0 - bfd: false - ebgp_multihop: 3 - route_map_out: TEST_OUT + send_community: all + maximum_routes: 1000 route_map_in: TEST_IN - local_as: '777' + route_map_out: TEST_OUT address_family_ipv4: peer_groups: - name: UNDERLAY-PEERS diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-LEAF1A.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-LEAF1A.yml index f007b9b5a94..a323de68be4 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-LEAF1A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-LEAF1A.yml @@ -569,9 +569,9 @@ router_ospf: - id: 9 vrf: Tenant_A_OP_Zone passive_interface_default: true + router_id: 192.168.42.42 no_passive_interfaces: - Vlan113 - router_id: 192.168.42.42 redistribute: bgp: enabled: true diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-LEAF2A.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-LEAF2A.yml index db8a5b26aa0..6b54862f8e6 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-LEAF2A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-LEAF2A.yml @@ -978,18 +978,18 @@ vlans: ip_access_lists: - name: TEST-IPV4-ACL-WITH-IP-FIELDS-IN_Vlan110 entries: - - sequence: 15 + - source: any + destination: 10.1.10.1 + sequence: 15 action: deny protocol: ip - source: any - destination: 10.1.10.1 - name: TEST-IPV4-ACL-WITH-IP-FIELDS-OUT_Vlan110 entries: - remark: Some remark will not require source and destination fields. - - action: permit - protocol: ip - source: 10.1.10.1 + - source: 10.1.10.1 destination: any + action: permit + protocol: ip ip_igmp_snooping: globally_enabled: true vlans: @@ -1218,18 +1218,18 @@ ipv6_static_routes: vrf: Tenant_D_OP_Zone - destination_address_prefix: 2001:dba::/32 gateway: 2001:db8:310::1 - name: Track-bfd-network-services track_bfd: true + name: Track-bfd-network-services vrf: Tenant_D_OP_Zone router_ospf: process_ids: - id: 16 vrf: Tenant_A_OSPF passive_interface_default: true + router_id: 192.168.255.10 no_passive_interfaces: - Ethernet22 - Ethernet23 - router_id: 192.168.255.10 redistribute: bgp: enabled: true diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-LEAF2B.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-LEAF2B.yml index 7da0e54ed29..535f579737d 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-LEAF2B.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-LEAF2B.yml @@ -923,18 +923,18 @@ vlans: ip_access_lists: - name: TEST-IPV4-ACL-WITH-IP-FIELDS-IN_Vlan110 entries: - - sequence: 15 + - source: any + destination: 10.1.10.1 + sequence: 15 action: deny protocol: ip - source: any - destination: 10.1.10.1 - name: TEST-IPV4-ACL-WITH-IP-FIELDS-OUT_Vlan110 entries: - remark: Some remark will not require source and destination fields. - - action: permit - protocol: ip - source: 10.1.10.1 + - source: 10.1.10.1 destination: any + action: permit + protocol: ip ip_igmp_snooping: globally_enabled: true vlans: @@ -1166,9 +1166,9 @@ router_ospf: - id: 16 vrf: Tenant_A_OSPF passive_interface_default: true + router_id: 192.168.255.11 no_passive_interfaces: - Ethernet24 - router_id: 192.168.255.11 redistribute: bgp: enabled: true diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-SVC3A.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-SVC3A.yml index 9e9ad2b98a5..69d1335e44d 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-SVC3A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-SVC3A.yml @@ -1679,18 +1679,18 @@ router_bfd: ip_access_lists: - name: TEST-IPV4-ACL-WITH-IP-FIELDS-IN_Vlan110 entries: - - sequence: 15 + - source: any + destination: 10.1.10.1 + sequence: 15 action: deny protocol: ip - source: any - destination: 10.1.10.1 - name: TEST-IPV4-ACL-WITH-IP-FIELDS-OUT_Vlan110 entries: - remark: Some remark will not require source and destination fields. - - action: permit - protocol: ip - source: 10.1.10.1 + - source: 10.1.10.1 destination: any + action: permit + protocol: ip ip_igmp_snooping: globally_enabled: true vlans: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-SVC3B.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-SVC3B.yml index 70a38434c6d..7d419e8da60 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-SVC3B.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1-SVC3B.yml @@ -1628,18 +1628,18 @@ router_bfd: ip_access_lists: - name: TEST-IPV4-ACL-WITH-IP-FIELDS-IN_Vlan110 entries: - - sequence: 15 + - source: any + destination: 10.1.10.1 + sequence: 15 action: deny protocol: ip - source: any - destination: 10.1.10.1 - name: TEST-IPV4-ACL-WITH-IP-FIELDS-OUT_Vlan110 entries: - remark: Some remark will not require source and destination fields. - - action: permit - protocol: ip - source: 10.1.10.1 + - source: 10.1.10.1 destination: any + action: permit + protocol: ip ip_igmp_snooping: globally_enabled: true vlans: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1_UNDEPLOYED_LEAF1A.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1_UNDEPLOYED_LEAF1A.yml index d73f5a5d68b..13ffd40524e 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1_UNDEPLOYED_LEAF1A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1_UNDEPLOYED_LEAF1A.yml @@ -1009,18 +1009,18 @@ router_bfd: ip_access_lists: - name: TEST-IPV4-ACL-WITH-IP-FIELDS-IN_Vlan110 entries: - - sequence: 15 + - source: any + destination: 10.1.10.1 + sequence: 15 action: deny protocol: ip - source: any - destination: 10.1.10.1 - name: TEST-IPV4-ACL-WITH-IP-FIELDS-OUT_Vlan110 entries: - remark: Some remark will not require source and destination fields. - - action: permit - protocol: ip - source: 10.1.10.1 + - source: 10.1.10.1 destination: any + action: permit + protocol: ip ip_igmp_snooping: globally_enabled: true vlans: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1_UNDEPLOYED_LEAF1B.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1_UNDEPLOYED_LEAF1B.yml index 454390c9b91..c6ebe9bcda8 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1_UNDEPLOYED_LEAF1B.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DC1_UNDEPLOYED_LEAF1B.yml @@ -1009,18 +1009,18 @@ router_bfd: ip_access_lists: - name: TEST-IPV4-ACL-WITH-IP-FIELDS-IN_Vlan110 entries: - - sequence: 15 + - source: any + destination: 10.1.10.1 + sequence: 15 action: deny protocol: ip - source: any - destination: 10.1.10.1 - name: TEST-IPV4-ACL-WITH-IP-FIELDS-OUT_Vlan110 entries: - remark: Some remark will not require source and destination fields. - - action: permit - protocol: ip - source: 10.1.10.1 + - source: 10.1.10.1 destination: any + action: permit + protocol: ip ip_igmp_snooping: globally_enabled: true vlans: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DUP-LEAF1.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DUP-LEAF1.yml index 330ffc8a93a..b24d475bd03 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DUP-LEAF1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DUP-LEAF1.yml @@ -96,7 +96,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.200.101/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DUP-LEAF2.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DUP-LEAF2.yml index 5c597dbebf2..25ce4c24f8e 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DUP-LEAF2.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/DUP-LEAF2.yml @@ -96,7 +96,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.200.102/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG-ISIS-L3LEAF1A.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG-ISIS-L3LEAF1A.yml index ea39ff3bd0a..4ead9f67943 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG-ISIS-L3LEAF1A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG-ISIS-L3LEAF1A.yml @@ -55,7 +55,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.201.116/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG-ISIS-L3LEAF1B.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG-ISIS-L3LEAF1B.yml index 051f55cb771..d97a029a65e 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG-ISIS-L3LEAF1B.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG-ISIS-L3LEAF1B.yml @@ -55,7 +55,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.201.117/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_IPV6_L3LEAF1A.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_IPV6_L3LEAF1A.yml index 4ec4212b041..429d091112a 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_IPV6_L3LEAF1A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_IPV6_L3LEAF1A.yml @@ -74,7 +74,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.201.116/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_IPV6_L3LEAF1B.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_IPV6_L3LEAF1B.yml index 604933a3d37..8c19878600d 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_IPV6_L3LEAF1B.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_IPV6_L3LEAF1B.yml @@ -74,7 +74,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.201.117/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_ODD_ID_L3LEAF1A.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_ODD_ID_L3LEAF1A.yml index f6cede56418..ddf2a7ca43a 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_ODD_ID_L3LEAF1A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_ODD_ID_L3LEAF1A.yml @@ -79,7 +79,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.201.116/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_ODD_ID_L3LEAF1B.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_ODD_ID_L3LEAF1B.yml index cb33b2b9168..9ef163a8f1c 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_ODD_ID_L3LEAF1B.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_ODD_ID_L3LEAF1B.yml @@ -79,7 +79,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.201.117/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_SAME_SUBNET_L3LEAF1A.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_SAME_SUBNET_L3LEAF1A.yml index a0c692ce56b..8fa779e2956 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_SAME_SUBNET_L3LEAF1A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_SAME_SUBNET_L3LEAF1A.yml @@ -109,7 +109,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.201.116/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_SAME_SUBNET_L3LEAF1B.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_SAME_SUBNET_L3LEAF1B.yml index c4af6de9089..407071dbc76 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_SAME_SUBNET_L3LEAF1B.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_SAME_SUBNET_L3LEAF1B.yml @@ -109,7 +109,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.201.117/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_SAME_SUBNET_L3LEAF2A.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_SAME_SUBNET_L3LEAF2A.yml index 2f15d3d2da0..7622ee448e7 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_SAME_SUBNET_L3LEAF2A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_SAME_SUBNET_L3LEAF2A.yml @@ -109,7 +109,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.201.118/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_SAME_SUBNET_L3LEAF2B.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_SAME_SUBNET_L3LEAF2B.yml index 95acbd88f78..b53f0e47b74 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_SAME_SUBNET_L3LEAF2B.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/MLAG_SAME_SUBNET_L3LEAF2B.yml @@ -109,7 +109,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.201.119/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/OVERLAY_ROUTING_PROTOCOL_CVX_SERVER1.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/OVERLAY_ROUTING_PROTOCOL_CVX_SERVER1.yml index 5044016eaf7..6321555029e 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/OVERLAY_ROUTING_PROTOCOL_CVX_SERVER1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/OVERLAY_ROUTING_PROTOCOL_CVX_SERVER1.yml @@ -23,7 +23,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.254.254/23 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/OVERLAY_ROUTING_PROTOCOL_CVX_SERVER2.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/OVERLAY_ROUTING_PROTOCOL_CVX_SERVER2.yml index 299d31ba2ac..191fae932cd 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/OVERLAY_ROUTING_PROTOCOL_CVX_SERVER2.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/OVERLAY_ROUTING_PROTOCOL_CVX_SERVER2.yml @@ -23,7 +23,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.254.255/23 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/OVERRIDE_VTEP_L3LEAF1A.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/OVERRIDE_VTEP_L3LEAF1A.yml index c8767437ba5..a08f9a6a0a5 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/OVERRIDE_VTEP_L3LEAF1A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/OVERRIDE_VTEP_L3LEAF1A.yml @@ -74,7 +74,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.201.116/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/OVERRIDE_VTEP_L3LEAF1B.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/OVERRIDE_VTEP_L3LEAF1B.yml index 5efeeeb72a0..86164fba29d 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/OVERRIDE_VTEP_L3LEAF1B.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/OVERRIDE_VTEP_L3LEAF1B.yml @@ -74,7 +74,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.201.117/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/SVI_PROFILE_NODE_1.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/SVI_PROFILE_NODE_1.yml index 8218972db3c..25306ea8169 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/SVI_PROFILE_NODE_1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/SVI_PROFILE_NODE_1.yml @@ -472,12 +472,12 @@ router_ospf: - id: 1 vrf: svi_profile_tests_vrf passive_interface_default: true + router_id: 192.168.255.1 no_passive_interfaces: - Vlan510 - Vlan511 - Vlan512 max_lsa: 15000 - router_id: 192.168.255.1 redistribute: bgp: enabled: true diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/SVI_PROFILE_NODE_2.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/SVI_PROFILE_NODE_2.yml index 989c074cf8e..3f10f469faf 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/SVI_PROFILE_NODE_2.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/SVI_PROFILE_NODE_2.yml @@ -344,12 +344,12 @@ router_ospf: - id: 1 vrf: svi_profile_tests_vrf passive_interface_default: true + router_id: 192.168.255.1 no_passive_interfaces: - Vlan510 - Vlan511 - Vlan512 max_lsa: 15000 - router_id: 192.168.255.1 redistribute: bgp: enabled: true diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/bgp-from-network-services-1.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/bgp-from-network-services-1.yml index 68c6025a437..1ffff610e15 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/bgp-from-network-services-1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/bgp-from-network-services-1.yml @@ -14,8 +14,8 @@ router_bgp: peer_groups: - name: MYPEERGROUP remote_as: '65991' - next_hop_self: true bfd: true + next_hop_self: true - name: MLAG-IPv4-UNDERLAY-PEER type: ipv4 remote_as: '65001' @@ -66,7 +66,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 10.1.1.1/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/bgp-from-network-services-2.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/bgp-from-network-services-2.yml index bcce2a31979..e194ae3152e 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/bgp-from-network-services-2.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/bgp-from-network-services-2.yml @@ -25,7 +25,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 10.1.1.2/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/core-1-isis-sr-ldp.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/core-1-isis-sr-ldp.yml index a16989714d4..bfd506aff18 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/core-1-isis-sr-ldp.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/core-1-isis-sr-ldp.yml @@ -248,6 +248,8 @@ ethernet_interfaces: igp_sync: true description: P2P_LINK_TO_CORE-2-OSPF-LDP_Ethernet10 speed: forced 1000full + l2_mru: 2222 + l2_mtu: 2222 - name: Ethernet12 peer: core-2-ospf-ldp peer_interface: Ethernet12 diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/core-2-ospf-ldp.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/core-2-ospf-ldp.yml index 2d5a037c490..d57edb98af2 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/core-2-ospf-ldp.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/core-2-ospf-ldp.yml @@ -190,6 +190,8 @@ ethernet_interfaces: igp_sync: true description: P2P_LINK_TO_CORE-1-ISIS-SR-LDP_Ethernet10 speed: forced 1000full + l2_mru: 2222 + l2_mtu: 2222 - name: Ethernet12 peer: core-1-isis-sr-ldp peer_interface: Ethernet12 diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/custom-structured-configuration.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/custom-structured-configuration.yml index f9d3e1fff29..5e2f6977c77 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/custom-structured-configuration.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/custom-structured-configuration.yml @@ -66,8 +66,6 @@ vrfs: - name: MGMT ip_routing: false management_api_http: - enable_vrfs: - - name: MGMT - enable_https: true -ip_igmp_snooping: - globally_enabled: true + enable_vrfs: [] + enable_https: null +ip_igmp_snooping: {} diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-custom-control-plane-policy-edge-1.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-custom-control-plane-policy-edge-1.yml index acc6fa6354f..0260dc280a1 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-custom-control-plane-policy-edge-1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-custom-control-plane-policy-edge-1.yml @@ -357,13 +357,13 @@ stun: application_traffic_recognition: application_profiles: - name: VIDEO - categories: - - name: VIDEO1 applications: - name: CUSTOM-APPLICATION-1 - name: skype application_transports: - rtp + categories: + - name: VIDEO1 - name: APP-PROFILE-CONTROL-PLANE applications: - name: APP-CONTROL-PLANE @@ -376,10 +376,10 @@ application_traffic_recognition: applications: ipv4_applications: - name: CUSTOM-APPLICATION-1 - protocols: - - tcp src_prefix_set_name: CUSTOM-SRC-PREFIX-1 dest_prefix_set_name: CUSTOM-DEST-PREFIX-1 + protocols: + - tcp - name: CUSTOM-APPLICATION-2 protocols: - tcp diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-custom-control-plane-policy-edge-2.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-custom-control-plane-policy-edge-2.yml index a1742aa1b9d..2ce52624a73 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-custom-control-plane-policy-edge-2.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-custom-control-plane-policy-edge-2.yml @@ -357,13 +357,13 @@ stun: application_traffic_recognition: application_profiles: - name: VIDEO - categories: - - name: VIDEO1 applications: - name: CUSTOM-APPLICATION-1 - name: skype application_transports: - rtp + categories: + - name: VIDEO1 - name: CUSTOM-CP-APP-PROFILE applications: - name: APP-CONTROL-PLANE @@ -376,10 +376,10 @@ application_traffic_recognition: applications: ipv4_applications: - name: CUSTOM-APPLICATION-1 - protocols: - - tcp src_prefix_set_name: CUSTOM-SRC-PREFIX-1 dest_prefix_set_name: CUSTOM-DEST-PREFIX-1 + protocols: + - tcp - name: CUSTOM-APPLICATION-2 protocols: - tcp diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-custom-control-plane-policy-pathfinder-1.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-custom-control-plane-policy-pathfinder-1.yml index fc00bd2545b..0e850d04416 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-custom-control-plane-policy-pathfinder-1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-custom-control-plane-policy-pathfinder-1.yml @@ -354,13 +354,13 @@ stun: application_traffic_recognition: application_profiles: - name: VIDEO - categories: - - name: VIDEO1 applications: - name: CUSTOM-APPLICATION-1 - name: skype application_transports: - rtp + categories: + - name: VIDEO1 - name: APP-PROFILE-CONTROL-PLANE applications: - name: APP-CONTROL-PLANE @@ -373,10 +373,10 @@ application_traffic_recognition: applications: ipv4_applications: - name: CUSTOM-APPLICATION-1 - protocols: - - tcp src_prefix_set_name: CUSTOM-SRC-PREFIX-1 dest_prefix_set_name: CUSTOM-DEST-PREFIX-1 + protocols: + - tcp - name: CUSTOM-APPLICATION-2 protocols: - tcp diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge.yml index 404a135929f..5d5afc6d38f 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge.yml @@ -664,13 +664,13 @@ stun: application_traffic_recognition: application_profiles: - name: VIDEO - categories: - - name: VIDEO1 applications: - name: CUSTOM-APPLICATION-1 - name: skype application_transports: - rtp + categories: + - name: VIDEO1 - name: VOICE applications: - name: CUSTOM-VOICE-APPLICATION @@ -687,10 +687,10 @@ application_traffic_recognition: applications: ipv4_applications: - name: CUSTOM-APPLICATION-1 - protocols: - - tcp src_prefix_set_name: CUSTOM-SRC-PREFIX-1 dest_prefix_set_name: CUSTOM-DEST-PREFIX-1 + protocols: + - tcp - name: CUSTOM-APPLICATION-2 protocols: - tcp @@ -927,33 +927,33 @@ metadata: - name: Tunnel100 preference: Preferred endpoint: - city: Fremont, CA + ip_address: 10.37.121.1 datacenter: FMT1 + city: Fremont, CA country: United States region: us-west1 latitude: '37' longitude: '-121' - ip_address: 10.37.121.1 - name: Tunnel101 preference: Alternate endpoint: - city: Washington, DC + ip_address: 10.39.77.1 datacenter: WAS1 + city: Washington, DC country: United States region: us-east1 latitude: '39' longitude: '-77' - ip_address: 10.39.77.1 - name: Tunnel102 preference: Alternate endpoint: - city: Frankfurt + ip_address: 10.50.9.1 datacenter: FRA4 + city: Frankfurt country: Germany region: eu-west1 latitude: '50' longitude: '9' - ip_address: 10.50.9.1 role: edge ssl_profile: profileA vtep_ip: 192.168.142.1 diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge1.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge1.yml index 84164529db0..de3888f213d 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge1.yml @@ -365,39 +365,39 @@ agents: ip_access_lists: - name: TEST-IPV4-ACL-WITH-IP-FIELDS-IN_Ethernet1_49.3 entries: - - sequence: 15 + - source: any + destination: 172.24.49.3 + sequence: 15 action: deny protocol: ip - source: any + - source: 172.24.49.2 destination: 172.24.49.3 - - action: permit + action: permit protocol: ip - source: 172.24.49.2 - destination: 172.24.49.3 - name: ACL-NAT-IE-DIRECT entries: - - sequence: 10 + - source: any + destination: 5.0.0.0/24 + sequence: 10 action: deny protocol: ip - source: any - destination: 5.0.0.0/24 - - sequence: 20 + - source: any + destination: any + sequence: 20 action: permit protocol: ip - source: any - destination: any - name: ACL-NAT-IE-ZSCALER entries: - - sequence: 10 + - source: any + destination: 10.0.0.0/24 + sequence: 10 action: permit protocol: ip - source: any - destination: 10.0.0.0/24 - - sequence: 20 + - source: any + destination: any + sequence: 20 action: deny protocol: ip - source: any - destination: any ip_extcommunity_lists: - name: ECL-EVPN-SOO entries: @@ -668,13 +668,13 @@ stun: application_traffic_recognition: application_profiles: - name: VIDEO - categories: - - name: VIDEO1 applications: - name: CUSTOM-APPLICATION-1 - name: skype application_transports: - rtp + categories: + - name: VIDEO1 - name: VOICE applications: - name: CUSTOM-VOICE-APPLICATION @@ -690,10 +690,10 @@ application_traffic_recognition: applications: ipv4_applications: - name: CUSTOM-APPLICATION-1 - protocols: - - tcp src_prefix_set_name: CUSTOM-SRC-PREFIX-1 dest_prefix_set_name: CUSTOM-DEST-PREFIX-1 + protocols: + - tcp - name: CUSTOM-APPLICATION-2 protocols: - tcp @@ -980,33 +980,33 @@ metadata: - name: Tunnel100 preference: Preferred endpoint: - city: Fremont, CA + ip_address: 10.37.121.1 datacenter: FMT1 + city: Fremont, CA country: United States region: us-west1 latitude: '37' longitude: '-121' - ip_address: 10.37.121.1 - name: Tunnel101 preference: Alternate endpoint: - city: Washington, DC + ip_address: 10.39.77.1 datacenter: WAS1 + city: Washington, DC country: United States region: us-east1 latitude: '39' longitude: '-77' - ip_address: 10.39.77.1 - name: Tunnel102 preference: Alternate endpoint: - city: Frankfurt + ip_address: 10.50.9.1 datacenter: FRA4 + city: Frankfurt country: Germany region: eu-west1 latitude: '50' longitude: '9' - ip_address: 10.50.9.1 - name: ZSCALER-EXIT-POLICY-2 type: zscaler city: Santa Clara, CA @@ -1022,33 +1022,33 @@ metadata: - name: Tunnel110 preference: Preferred endpoint: - city: Fremont, CA + ip_address: 10.37.121.1 datacenter: FMT1 + city: Fremont, CA country: United States region: us-west1 latitude: '37' longitude: '-121' - ip_address: 10.37.121.1 - name: Tunnel111 preference: Alternate endpoint: - city: Washington, DC + ip_address: 10.39.77.1 datacenter: WAS1 + city: Washington, DC country: United States region: us-east1 latitude: '39' longitude: '-77' - ip_address: 10.39.77.1 - name: Tunnel112 preference: Alternate endpoint: - city: Frankfurt + ip_address: 10.50.9.1 datacenter: FRA4 + city: Frankfurt country: Germany region: eu-west1 latitude: '50' longitude: '9' - ip_address: 10.50.9.1 role: edge ssl_profile: profileA vtep_ip: 192.168.142.2 diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge2A.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge2A.yml index bde66170a15..e5b55b5cdaa 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge2A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge2A.yml @@ -655,13 +655,13 @@ stun: application_traffic_recognition: application_profiles: - name: VIDEO - categories: - - name: VIDEO1 applications: - name: CUSTOM-APPLICATION-1 - name: skype application_transports: - rtp + categories: + - name: VIDEO1 - name: VOICE applications: - name: CUSTOM-VOICE-APPLICATION @@ -678,10 +678,10 @@ application_traffic_recognition: applications: ipv4_applications: - name: CUSTOM-APPLICATION-1 - protocols: - - tcp src_prefix_set_name: CUSTOM-SRC-PREFIX-1 dest_prefix_set_name: CUSTOM-DEST-PREFIX-1 + protocols: + - tcp - name: CUSTOM-APPLICATION-2 protocols: - tcp diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge2B.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge2B.yml index e610465e0a2..13d4ac9ac68 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge2B.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge2B.yml @@ -637,13 +637,13 @@ stun: application_traffic_recognition: application_profiles: - name: VIDEO - categories: - - name: VIDEO1 applications: - name: CUSTOM-APPLICATION-1 - name: skype application_transports: - rtp + categories: + - name: VIDEO1 - name: VOICE applications: - name: CUSTOM-VOICE-APPLICATION @@ -660,10 +660,10 @@ application_traffic_recognition: applications: ipv4_applications: - name: CUSTOM-APPLICATION-1 - protocols: - - tcp src_prefix_set_name: CUSTOM-SRC-PREFIX-1 dest_prefix_set_name: CUSTOM-DEST-PREFIX-1 + protocols: + - tcp - name: CUSTOM-APPLICATION-2 protocols: - tcp diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge3A.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge3A.yml index ab8a15b0eca..effa2d4a8b3 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge3A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge3A.yml @@ -473,13 +473,13 @@ stun: application_traffic_recognition: application_profiles: - name: VIDEO - categories: - - name: VIDEO1 applications: - name: CUSTOM-APPLICATION-1 - name: skype application_transports: - rtp + categories: + - name: VIDEO1 - name: VOICE applications: - name: CUSTOM-VOICE-APPLICATION @@ -496,10 +496,10 @@ application_traffic_recognition: applications: ipv4_applications: - name: CUSTOM-APPLICATION-1 - protocols: - - tcp src_prefix_set_name: CUSTOM-SRC-PREFIX-1 dest_prefix_set_name: CUSTOM-DEST-PREFIX-1 + protocols: + - tcp - name: CUSTOM-APPLICATION-2 protocols: - tcp diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge3B.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge3B.yml index 96ee839e258..451caef49c9 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge3B.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge3B.yml @@ -471,13 +471,13 @@ stun: application_traffic_recognition: application_profiles: - name: VIDEO - categories: - - name: VIDEO1 applications: - name: CUSTOM-APPLICATION-1 - name: skype application_transports: - rtp + categories: + - name: VIDEO1 - name: VOICE applications: - name: CUSTOM-VOICE-APPLICATION @@ -494,10 +494,10 @@ application_traffic_recognition: applications: ipv4_applications: - name: CUSTOM-APPLICATION-1 - protocols: - - tcp src_prefix_set_name: CUSTOM-SRC-PREFIX-1 dest_prefix_set_name: CUSTOM-DEST-PREFIX-1 + protocols: + - tcp - name: CUSTOM-APPLICATION-2 protocols: - tcp diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge4A.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge4A.yml index 4ffc3cacbfa..84006493a56 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge4A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge4A.yml @@ -496,13 +496,13 @@ stun: application_traffic_recognition: application_profiles: - name: VIDEO - categories: - - name: VIDEO1 applications: - name: CUSTOM-APPLICATION-1 - name: skype application_transports: - rtp + categories: + - name: VIDEO1 - name: VOICE applications: - name: CUSTOM-VOICE-APPLICATION @@ -519,10 +519,10 @@ application_traffic_recognition: applications: ipv4_applications: - name: CUSTOM-APPLICATION-1 - protocols: - - tcp src_prefix_set_name: CUSTOM-SRC-PREFIX-1 dest_prefix_set_name: CUSTOM-DEST-PREFIX-1 + protocols: + - tcp - name: CUSTOM-APPLICATION-2 protocols: - tcp diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge4B.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge4B.yml index 8a3981ab1ff..cfa89076411 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge4B.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-edge4B.yml @@ -496,13 +496,13 @@ stun: application_traffic_recognition: application_profiles: - name: VIDEO - categories: - - name: VIDEO1 applications: - name: CUSTOM-APPLICATION-1 - name: skype application_transports: - rtp + categories: + - name: VIDEO1 - name: VOICE applications: - name: CUSTOM-VOICE-APPLICATION @@ -519,10 +519,10 @@ application_traffic_recognition: applications: ipv4_applications: - name: CUSTOM-APPLICATION-1 - protocols: - - tcp src_prefix_set_name: CUSTOM-SRC-PREFIX-1 dest_prefix_set_name: CUSTOM-DEST-PREFIX-1 + protocols: + - tcp - name: CUSTOM-APPLICATION-2 protocols: - tcp diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-pathfinder.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-pathfinder.yml index 1954c6e0ea3..a16d246a099 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-pathfinder.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-pathfinder.yml @@ -417,13 +417,13 @@ stun: application_traffic_recognition: application_profiles: - name: VIDEO - categories: - - name: VIDEO1 applications: - name: CUSTOM-APPLICATION-1 - name: skype application_transports: - rtp + categories: + - name: VIDEO1 - name: VOICE applications: - name: CUSTOM-VOICE-APPLICATION @@ -440,10 +440,10 @@ application_traffic_recognition: applications: ipv4_applications: - name: CUSTOM-APPLICATION-1 - protocols: - - tcp src_prefix_set_name: CUSTOM-SRC-PREFIX-1 dest_prefix_set_name: CUSTOM-DEST-PREFIX-1 + protocols: + - tcp - name: CUSTOM-APPLICATION-2 protocols: - tcp diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-pathfinder1.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-pathfinder1.yml index d4bad054aba..fb494dc1aca 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-pathfinder1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-pathfinder1.yml @@ -434,13 +434,13 @@ stun: application_traffic_recognition: application_profiles: - name: VIDEO - categories: - - name: VIDEO1 applications: - name: CUSTOM-APPLICATION-1 - name: skype application_transports: - rtp + categories: + - name: VIDEO1 - name: VOICE applications: - name: CUSTOM-VOICE-APPLICATION @@ -457,10 +457,10 @@ application_traffic_recognition: applications: ipv4_applications: - name: CUSTOM-APPLICATION-1 - protocols: - - tcp src_prefix_set_name: CUSTOM-SRC-PREFIX-1 dest_prefix_set_name: CUSTOM-DEST-PREFIX-1 + protocols: + - tcp - name: CUSTOM-APPLICATION-2 protocols: - tcp diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-pathfinder2.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-pathfinder2.yml index 70ec794a682..6da01081346 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-pathfinder2.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-pathfinder2.yml @@ -452,13 +452,13 @@ stun: application_traffic_recognition: application_profiles: - name: VIDEO - categories: - - name: VIDEO1 applications: - name: CUSTOM-APPLICATION-1 - name: skype application_transports: - rtp + categories: + - name: VIDEO1 - name: VOICE applications: - name: CUSTOM-VOICE-APPLICATION @@ -475,10 +475,10 @@ application_traffic_recognition: applications: ipv4_applications: - name: CUSTOM-APPLICATION-1 - protocols: - - tcp src_prefix_set_name: CUSTOM-SRC-PREFIX-1 dest_prefix_set_name: CUSTOM-DEST-PREFIX-1 + protocols: + - tcp - name: CUSTOM-APPLICATION-2 protocols: - tcp diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-transit1A.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-transit1A.yml index a5ea38924a4..b42ca1cd3e3 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-transit1A.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-transit1A.yml @@ -691,13 +691,13 @@ stun: application_traffic_recognition: application_profiles: - name: VIDEO - categories: - - name: VIDEO1 applications: - name: CUSTOM-APPLICATION-1 - name: skype application_transports: - rtp + categories: + - name: VIDEO1 - name: VOICE applications: - name: CUSTOM-VOICE-APPLICATION @@ -714,10 +714,10 @@ application_traffic_recognition: applications: ipv4_applications: - name: CUSTOM-APPLICATION-1 - protocols: - - tcp src_prefix_set_name: CUSTOM-SRC-PREFIX-1 dest_prefix_set_name: CUSTOM-DEST-PREFIX-1 + protocols: + - tcp - name: CUSTOM-APPLICATION-2 protocols: - tcp diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-transit1B.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-transit1B.yml index 56a2ed5ddad..4b42d7cbaa8 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-transit1B.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/cv-pathfinder-transit1B.yml @@ -688,13 +688,13 @@ stun: application_traffic_recognition: application_profiles: - name: VIDEO - categories: - - name: VIDEO1 applications: - name: CUSTOM-APPLICATION-1 - name: skype application_transports: - rtp + categories: + - name: VIDEO1 - name: VOICE applications: - name: CUSTOM-VOICE-APPLICATION @@ -711,10 +711,10 @@ application_traffic_recognition: applications: ipv4_applications: - name: CUSTOM-APPLICATION-1 - protocols: - - tcp src_prefix_set_name: CUSTOM-SRC-PREFIX-1 dest_prefix_set_name: CUSTOM-DEST-PREFIX-1 + protocols: + - tcp - name: CUSTOM-APPLICATION-2 protocols: - tcp diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/evpn_l2_multi_domain.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/evpn_l2_multi_domain.yml index c0a7eeb913d..76053740f8a 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/evpn_l2_multi_domain.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/evpn_l2_multi_domain.yml @@ -303,7 +303,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.100.101/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/evpn_services_l2_only_false.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/evpn_services_l2_only_false.yml index 87d46dd841c..1c9f99e5f53 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/evpn_services_l2_only_false.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/evpn_services_l2_only_false.yml @@ -666,18 +666,18 @@ vlans: ip_access_lists: - name: TEST-IPV4-ACL-WITH-IP-FIELDS-IN_Vlan110 entries: - - sequence: 15 + - source: any + destination: 10.1.10.1 + sequence: 15 action: deny protocol: ip - source: any - destination: 10.1.10.1 - name: TEST-IPV4-ACL-WITH-IP-FIELDS-OUT_Vlan110 entries: - remark: Some remark will not require source and destination fields. - - action: permit - protocol: ip - source: 10.1.10.1 + - source: 10.1.10.1 destination: any + action: permit + protocol: ip ip_igmp_snooping: globally_enabled: true vlans: @@ -995,9 +995,9 @@ router_ospf: process_ids: - id: 123 passive_interface_default: true + router_id: 192.168.255.109 no_passive_interfaces: - Vlan1234 - router_id: 192.168.255.109 redistribute: bgp: enabled: true diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/ignore-custom-keys-in-data-models.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/ignore-custom-keys-in-data-models.yml index ab0eefdfc1b..525059a96a6 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/ignore-custom-keys-in-data-models.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/ignore-custom-keys-in-data-models.yml @@ -21,11 +21,11 @@ management_api_http: enable_https: true ip_igmp_snooping: globally_enabled: true -_custom_key2: -- custom_value2 ethernet_interfaces: - name: Ethernet1 switchport: enabled: true _custom_key3: custom_dict3: custom_value3 +_custom_key2: +- custom_value2 diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/ipv4-acls.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/ipv4-acls.yml index 07a575b0515..611066ee156 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/ipv4-acls.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/ipv4-acls.yml @@ -134,70 +134,70 @@ route_maps: ip_access_lists: - name: TEST-IPV4-ACL-WITH-IP-FIELDS-IN_Ethernet1 entries: - - sequence: 15 + - source: any + destination: 172.16.0.2 + sequence: 15 action: deny protocol: ip - source: any + - source: 172.16.0.1/30 destination: 172.16.0.2 - - action: permit + action: permit protocol: ip - source: 172.16.0.1/30 - destination: 172.16.0.2 - name: TEST-IPV4-ACL-WITH-IP-FIELDS-IN_Ethernet2 entries: - - sequence: 15 + - source: any + destination: 172.17.17.17 + sequence: 15 action: deny protocol: ip - source: any + - source: 172.17.17.1 destination: 172.17.17.17 - - action: permit + action: permit protocol: ip - source: 172.17.17.1 - destination: 172.17.17.17 - name: TEST-IPV4-ACL-WITH-IP-FIELDS-IN_Ethernet5_1 entries: - - sequence: 15 + - source: any + destination: 172.20.20.0 + sequence: 15 action: deny protocol: ip - source: any + - source: 172.20.20.1/30 destination: 172.20.20.0 - - action: permit + action: permit protocol: ip - source: 172.20.20.1/30 - destination: 172.20.20.0 - name: TEST-IPV4-ACL-WITH-IP-FIELDS-OUT_Ethernet1 entries: - remark: Some remark will not require source and destination fields. - - action: permit - protocol: ip - source: 172.16.0.2 + - source: 172.16.0.2 destination: any + action: permit + protocol: ip - name: TEST-IPV4-ACL-WITH-IP-FIELDS-OUT_Ethernet2 entries: - remark: Some remark will not require source and destination fields. - - action: permit - protocol: ip - source: 172.17.17.17 + - source: 172.17.17.17 destination: any + action: permit + protocol: ip - name: TEST-IPV4-ACL-WITH-IP-FIELDS-OUT_Ethernet6_6.6 entries: - remark: Some remark will not require source and destination fields. - - action: permit - protocol: ip - source: 172.21.21.0 + - source: 172.21.21.0 destination: any + action: permit + protocol: ip - name: TEST-IPV4-ACL-WITH-NO-FIELDS-IN entries: - - action: permit - protocol: ip - source: 172.18.18.18 + - source: 172.18.18.18 destination: any + action: permit + protocol: ip - name: TEST-IPV4-ACL-WITH-NO-FIELDS-OUT entries: - - action: permit - protocol: ip - source: 172.18.18.18 + - source: 172.18.18.18 destination: any + action: permit + protocol: ip router_bfd: multihop: interval: 300 diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/mgmt_interface_ipv6.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/mgmt_interface_ipv6.yml index 88e0c90e23b..eb955a02dd0 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/mgmt_interface_ipv6.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/mgmt_interface_ipv6.yml @@ -25,8 +25,6 @@ management_interfaces: description: OOB_MANAGEMENT shutdown: false vrf: MGMT - ip_address: null - gateway: null type: oob ipv6_enable: true ipv6_address: 0200::105/64 diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/no_mgmt_gateway.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/no_mgmt_gateway.yml index 65db29d163c..108036eb68c 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/no_mgmt_gateway.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/no_mgmt_gateway.yml @@ -21,7 +21,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.200.106 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/ntp-settings-1.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/ntp-settings-1.yml index 219e39abf3c..6d07291defe 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/ntp-settings-1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/ntp-settings-1.yml @@ -21,7 +21,6 @@ management_interfaces: shutdown: false vrf: MGMT ip_address: 192.168.0.2/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/platform_settings.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/platform_settings.yml index 10d10a2e527..9b37388aee3 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/platform_settings.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/platform_settings.yml @@ -29,6 +29,6 @@ ip_igmp_snooping: globally_enabled: true ethernet_interfaces: - name: Ethernet12 + description: Interface Created from platform_settings.structured_config switchport: enabled: true - description: Interface Created from platform_settings.structured_config diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/snmp-settings-1.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/snmp-settings-1.yml index 4a8edd8d3ee..e629223d581 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/snmp-settings-1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/snmp-settings-1.yml @@ -43,41 +43,41 @@ snmp_server: priv_passphrase: clearpriv hosts: - host: 10.6.75.121 + vrf: SNMPVRF version: '1' community: SNMP-COMMUNITY-1 - vrf: SNMPVRF - host: 10.6.75.123 + vrf: MGMT version: 2c community: SNMP-COMMUNITY-2 - vrf: MGMT - host: 10.6.75.123 + vrf: SNMPVRF version: 2c community: SNMP-COMMUNITY-2 - vrf: SNMPVRF - host: 10.6.75.124 + vrf: MGMT version: '3' users: - username: USER-WRITE authentication_level: auth - vrf: MGMT - host: 10.6.75.125 + vrf: SNMPVRF version: 2c community: SNMP-COMMUNITY-2 - vrf: SNMPVRF - host: 10.6.75.127 + vrf: MGMT version: 2c community: SNMP-COMMUNITY-2 - vrf: MGMT - host: 10.6.75.127 + vrf: SNMPVRF version: 2c community: SNMP-COMMUNITY-2 - vrf: SNMPVRF - host: 10.6.75.128 + vrf: MGMT version: '3' users: - username: USER-WRITE authentication_level: auth - vrf: MGMT vrfs: - name: default enable: false diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/snmp-settings-2.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/snmp-settings-2.yml index 3e982ae9e15..ec3e9841763 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/snmp-settings-2.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/snmp-settings-2.yml @@ -25,9 +25,9 @@ snmp_server: version: 2c community: SNMP-COMMUNITY-2 - host: 10.6.75.125 + vrf: SNMPVRF version: 2c community: SNMP-COMMUNITY-2 - vrf: SNMPVRF - host: 10.6.75.126 version: '3' users: @@ -37,9 +37,9 @@ snmp_server: version: 2c community: SNMP-COMMUNITY-2 - host: 10.6.75.127 + vrf: SNMPVRF version: 2c community: SNMP-COMMUNITY-2 - vrf: SNMPVRF - host: 10.6.75.128 version: '3' users: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/source-interfaces.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/source-interfaces.yml index 3b91100bea5..07f8afc92d1 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/source-interfaces.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/source-interfaces.yml @@ -22,7 +22,6 @@ management_interfaces: shutdown: false vrf: default ip_address: 192.168.0.2/24 - gateway: null type: oob management_api_http: enable_vrfs: diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/group_vars/CORE_UNIT_TESTS.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/group_vars/CORE_UNIT_TESTS.yml index 9369c8e3ee3..5e6ebb4f3b1 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/group_vars/CORE_UNIT_TESTS.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/group_vars/CORE_UNIT_TESTS.yml @@ -77,6 +77,9 @@ core_interfaces: speed: "forced 1000full" mtu: 1500 ip_pool: underlay_pool + # Testing merge of structured config on profile and link. + structured_config: + l2_mtu: 2222 p2p_links: @@ -139,6 +142,9 @@ core_interfaces: id: 7 interfaces: [ Ethernet10, Ethernet10 ] profile: ospf_bb_profile + # Testing merge of structured config on profile and link. + structured_config: + l2_mru: 2222 # core Port-Channel - nodes: [ core-1-isis-sr-ldp, core-2-ospf-ldp ] diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/group_vars/UPLINK_MLAG_STRUCTURED_CONFIG_L2LEAFS.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/group_vars/UPLINK_MLAG_STRUCTURED_CONFIG_L2LEAFS.yml index c79f4ddeb7c..b1f4456fec4 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/group_vars/UPLINK_MLAG_STRUCTURED_CONFIG_L2LEAFS.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/group_vars/UPLINK_MLAG_STRUCTURED_CONFIG_L2LEAFS.yml @@ -11,30 +11,46 @@ l2leaf: level: 25 unknown_unicast: level: 25 - switchport: - trunk: - native_vlan_tag: true mlag_interfaces: [ Ethernet3, Ethernet4 ] mlag_peer_ipv4_pool: 10.255.252.0/24 - mlag_port_channel_structured_config: - storm_control: - broadcast: - level: 25 - unknown_unicast: - level: 25 - switchport: - trunk: - native_vlan_tag: true + mlag_port_channel_structured_config: # Setting structured config here but it is overridden by 'null' on group level and applied again on node level. + description: "Port-channel description not being used because it is overridden by 'null' on node-group level." + spanning_tree_mode: mstp spanning_tree_priority: 16384 node_groups: - group: UPLINK-MLAG-STRUCTURED-CONFIG-L2LEAF1 + # Testing the inheritance works correctly when nullifying a dict in the group and then applying a new one per node. + mlag_port_channel_structured_config: null + # Testing merging of uplink_structured_config which is a dict type with no schema. + uplink_structured_config: + switchport: + trunk: + native_vlan_tag: true nodes: - name: UPLINK-MLAG-STRUCTURED-CONFIG-L2LEAF1A id: 1 mgmt_ip: 192.168.201.201/24 uplink_switch_interfaces: [ Ethernet5, Ethernet5 ] + mlag_port_channel_structured_config: + storm_control: + broadcast: + level: 25 + unknown_unicast: + level: 25 + switchport: + trunk: + native_vlan_tag: true - name: UPLINK-MLAG-STRUCTURED-CONFIG-L2LEAF1B id: 2 mgmt_ip: 192.168.201.201/24 uplink_switch_interfaces: [ Ethernet6, Ethernet6 ] + mlag_port_channel_structured_config: + storm_control: + broadcast: + level: 25 + unknown_unicast: + level: 25 + switchport: + trunk: + native_vlan_tag: true diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/host_vars/custom-structured-configuration.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/host_vars/custom-structured-configuration.yml index 5cbc451d6f1..961615d97a9 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/host_vars/custom-structured-configuration.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/host_vars/custom-structured-configuration.yml @@ -88,3 +88,16 @@ csc_2_local_users: privilege: 2 role: network-operator sha512_password: "$6$rkvZergVBQ09WJte$.6wtRT8ITilT06pdXS0s5u7M.7G54B8xPPqKTPIhqyCkw6/QgqP2j4yoYAo7YKVU/S3Ra8p23kMtbdHsoBWIk." + +# DATA MODEL WITH EMPTY LIST, EMPTY DICT and NONE AS VALUES + +csc_1_management_api_http: + enable_vrfs: null # Replacing the default list with null. + enable_https: null # Replacing the default boolean with null. + +csc_2_management_api_http: + enable_vrfs: [] # Replacing the null above with an empty list. + +csc_1_ip_igmp_snooping: null # Replacing the default dict with null. + +csc_2_ip_igmp_snooping: {} # Replacing the null above with an empty dict. diff --git a/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc1-leaf1a.yml b/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc1-leaf1a.yml index 8e9fe80de5a..f21c4fc3421 100644 --- a/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc1-leaf1a.yml +++ b/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc1-leaf1a.yml @@ -82,8 +82,8 @@ router_bgp: description: dc1-spine2_Loopback0 remote_as: '65100' - ip_address: 10.1.1.1 - description: External peer peer_group: EVPN-OVERLAY-PEERS + description: External peer address_family_evpn: peer_groups: - name: EVPN-OVERLAY-PEERS diff --git a/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc1-leaf2c.yml b/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc1-leaf2c.yml index f31f928605d..eb064bed26a 100644 --- a/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc1-leaf2c.yml +++ b/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc1-leaf2c.yml @@ -119,8 +119,8 @@ vxlan_interface: Vxlan1: description: dc1-leaf2c_VTEP vxlan: - udp_port: 4789 source_interface: Loopback1 + udp_port: 4789 virtual_router_encapsulation_mac_address: mlag-system-id vlans: - id: 11 diff --git a/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc1-spine1.yml b/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc1-spine1.yml index 12758419496..44cf30a7f89 100644 --- a/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc1-spine1.yml +++ b/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc1-spine1.yml @@ -104,35 +104,35 @@ router_bgp: remote_as: '65133' - ip_address: 123.1.1.10 remote_as: '1234' - password: oBztv71m2uhR7hh58/OCNA== + local_as: '123' description: External IPv4 BGP peer - send_community: standard extended - maximum_routes: 0 + password: oBztv71m2uhR7hh58/OCNA== + update_source: Loopback123 + route_map_in: RM-123-1-1-10-IN + route_map_out: RM-Tenant_A_WAN_Zone-123.1.1.10-SET-NEXT-HOP-OUT default_originate: always: false route_map: RM-Tenant_A_WAN_Zone-123.1.1.10-SET-NEXT-HOP-OUT - update_source: Loopback123 + send_community: standard extended + maximum_routes: 0 ebgp_multihop: 3 - route_map_in: RM-123-1-1-10-IN - route_map_out: RM-Tenant_A_WAN_Zone-123.1.1.10-SET-NEXT-HOP-OUT - local_as: '123' - ip_address: 123.1.1.11 remote_as: '1234' - password: oBztv71m2uhR7hh58/OCNA== + local_as: '123' description: External IPv4 BGP peer - send_community: standard extended - maximum_routes: 0 - default_originate: - always: false + password: oBztv71m2uhR7hh58/OCNA== update_source: Loopback123 - ebgp_multihop: 3 route_map_in: RM-123-1-1-11-IN route_map_out: RM-123-1-1-11-OUT - local_as: '123' + default_originate: + always: false + send_community: standard extended + maximum_routes: 0 + ebgp_multihop: 3 - ip_address: fd5a:fe45:8831:06c5::a remote_as: '12345' - send_community: all route_map_out: RM-Tenant_A_WAN_Zone-fd5a:fe45:8831:06c5::a-SET-NEXT-HOP-OUT + send_community: all - ip_address: fd5a:fe45:8831:06c5::b remote_as: '12345' address_family_evpn: diff --git a/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc2-leaf3a.arista.com.yml b/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc2-leaf3a.arista.com.yml index 89908817452..6be0a725a78 100644 --- a/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc2-leaf3a.arista.com.yml +++ b/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc2-leaf3a.arista.com.yml @@ -320,23 +320,23 @@ port_channel_interfaces: shutdown: false - name: Port-Channel11 description: dc2-leaf3-fw1_PortChannel + vlans: 11-12,21-22 type: switched mode: trunk - vlans: 11-12,21-22 native_vlan: 4092 - spanning_tree_portfast: edge mlag: 11 + spanning_tree_portfast: edge - name: Port-Channel12 description: Test_mode_and_vlans + vlans: '100' type: switched mode: access - vlans: '100' - name: Port-Channel13 description: Test_native_vlan_and_trunk_groups type: switched + mode: trunk native_vlan: 4092 native_vlan_tag: true - mode: trunk trunk_groups: - MLAG - name: Port-Channel14 @@ -344,8 +344,8 @@ port_channel_interfaces: type: switched mode: trunk phone phone: - vlan: 20 trunk: tagged + vlan: 20 - name: Port-Channel15 description: Test_type_routed type: routed @@ -394,41 +394,41 @@ ethernet_interfaces: enabled: false ip_address: 10.255.255.123/31 - name: Ethernet11 - peer: dc2-leaf3-fw1 - peer_interface: e1 - peer_type: firewall description: dc2-leaf3-fw1_e1 type: port-channel-member channel_group: id: 11 mode: active + peer: dc2-leaf3-fw1 + peer_interface: e1 + peer_type: firewall - name: Ethernet12 description: Test_mode_and_vlans - type: switched - mode: access vlans: '100' + mode: access + type: switched - name: Ethernet13 description: Test_native_vlan_and_trunk_groups - type: switched native_vlan: 4092 native_vlan_tag: true mode: trunk trunk_groups: - MLAG + type: switched - name: Ethernet14 description: Test_phone - type: switched mode: trunk phone phone: - vlan: 20 trunk: tagged + vlan: 20 + type: switched - name: Ethernet15 description: Test_type_routed + shutdown: false type: routed ip_address: 1.1.1.1/24 peer: dc2-leaf2b peer_interface: Ethernet2 - shutdown: false mlag_configuration: domain_id: DC2_L3_LEAF3 local_interface: Vlan4094 diff --git a/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc2-leaf3b.arista.com.yml b/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc2-leaf3b.arista.com.yml index de675186fbf..b39c3194c0a 100644 --- a/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc2-leaf3b.arista.com.yml +++ b/ansible_collections/arista/avd/molecule/eos_validate_state/intended/structured_configs/dc2-leaf3b.arista.com.yml @@ -320,12 +320,12 @@ port_channel_interfaces: shutdown: false - name: Port-Channel11 description: dc2-leaf3-fw1_PortChannel + vlans: 11-12,21-22 type: switched mode: trunk - vlans: 11-12,21-22 native_vlan: 4092 - spanning_tree_portfast: edge mlag: 11 + spanning_tree_portfast: edge ethernet_interfaces: - name: Ethernet3 peer: dc2-leaf3a.arista.com @@ -366,14 +366,14 @@ ethernet_interfaces: enabled: false ip_address: 10.255.255.127/31 - name: Ethernet11 - peer: dc2-leaf3-fw1 - peer_interface: e1 - peer_type: firewall description: dc2-leaf3-fw1_e1 type: port-channel-member channel_group: id: 11 mode: active + peer: dc2-leaf3-fw1 + peer_interface: e1 + peer_type: firewall mlag_configuration: domain_id: DC2_L3_LEAF3 local_interface: Vlan4094 diff --git a/ansible_collections/arista/avd/molecule/evpn_underlay_ebgp_overlay_ebgp/intended/structured_configs/DC1-BL1A.yml b/ansible_collections/arista/avd/molecule/evpn_underlay_ebgp_overlay_ebgp/intended/structured_configs/DC1-BL1A.yml index 50aae3245c6..cb0dd5a89db 100644 --- a/ansible_collections/arista/avd/molecule/evpn_underlay_ebgp_overlay_ebgp/intended/structured_configs/DC1-BL1A.yml +++ b/ansible_collections/arista/avd/molecule/evpn_underlay_ebgp_overlay_ebgp/intended/structured_configs/DC1-BL1A.yml @@ -121,8 +121,8 @@ router_bgp: neighbors: - ip_address: 123.1.1.10 remote_as: '1234' - password: oBztv71m2uhR7hh58/OCNA== description: External IPv4 BGP peer + password: oBztv71m2uhR7hh58/OCNA== send_community: standard extended maximum_routes: 0 default_originate: @@ -130,21 +130,21 @@ router_bgp: route_map: RM-Tenant_A_WAN_Zone-123.1.1.10-SET-NEXT-HOP-OUT update_source: Loopback123 ebgp_multihop: 3 - route_map_in: RM-123-1-1-10-IN route_map_out: RM-Tenant_A_WAN_Zone-123.1.1.10-SET-NEXT-HOP-OUT + route_map_in: RM-123-1-1-10-IN local_as: '123' - ip_address: 123.1.1.11 remote_as: '1234' - password: oBztv71m2uhR7hh58/OCNA== description: External IPv4 BGP peer + password: oBztv71m2uhR7hh58/OCNA== send_community: standard extended maximum_routes: 0 default_originate: always: false update_source: Loopback123 ebgp_multihop: 3 - route_map_in: RM-123-1-1-11-IN route_map_out: RM-123-1-1-11-OUT + route_map_in: RM-123-1-1-11-IN local_as: '123' - ip_address: fd5a:fe45:8831:06c5::a remote_as: '12345' @@ -245,15 +245,15 @@ static_routes: gateway: 1.2.3.4 vrf: Tenant_A_WAN_Zone - destination_address_prefix: 1.1.1.0/24 - interface: vlan101 gateway: 10.1.1.1 + interface: vlan101 vrf: Tenant_A_WAN_Zone - destination_address_prefix: 1.1.2.0/24 - interface: vlan101 gateway: 10.1.1.1 distance: 200 tag: 666 name: RT-TO-FAKE-DMZ + interface: vlan101 vrf: Tenant_A_WAN_Zone - destination_address_prefix: 10.3.5.0/24 interface: Null0 @@ -454,14 +454,14 @@ ethernet_interfaces: shutdown: false - name: Ethernet4000 description: My test - ip_address: 10.3.2.1/21 shutdown: false - switchport: - enabled: false mtu: 1500 + ip_address: 10.3.2.1/21 peer: MY-own-peer peer_interface: Ethernet123 peer_type: my_precious + switchport: + enabled: false loopback_interfaces: - name: Loopback0 description: CUSTOM_EVPN_Overlay_Peering_L3LEAF diff --git a/ansible_collections/arista/avd/molecule/evpn_underlay_ebgp_overlay_ebgp/intended/structured_configs/DC1-BL1B.yml b/ansible_collections/arista/avd/molecule/evpn_underlay_ebgp_overlay_ebgp/intended/structured_configs/DC1-BL1B.yml index f15892f63b7..e51a6befa3d 100644 --- a/ansible_collections/arista/avd/molecule/evpn_underlay_ebgp_overlay_ebgp/intended/structured_configs/DC1-BL1B.yml +++ b/ansible_collections/arista/avd/molecule/evpn_underlay_ebgp_overlay_ebgp/intended/structured_configs/DC1-BL1B.yml @@ -121,8 +121,8 @@ router_bgp: neighbors: - ip_address: 123.1.1.10 remote_as: '1234' - password: oBztv71m2uhR7hh58/OCNA== description: External IPv4 BGP peer + password: oBztv71m2uhR7hh58/OCNA== send_community: standard extended maximum_routes: 0 default_originate: @@ -130,21 +130,21 @@ router_bgp: route_map: RM-Tenant_A_WAN_Zone-123.1.1.10-SET-NEXT-HOP-OUT update_source: Loopback123 ebgp_multihop: 3 - route_map_in: RM-123-1-1-10-IN route_map_out: RM-Tenant_A_WAN_Zone-123.1.1.10-SET-NEXT-HOP-OUT + route_map_in: RM-123-1-1-10-IN local_as: '123' - ip_address: 123.1.1.11 remote_as: '1234' - password: oBztv71m2uhR7hh58/OCNA== description: External IPv4 BGP peer + password: oBztv71m2uhR7hh58/OCNA== send_community: standard extended maximum_routes: 0 default_originate: always: false update_source: Loopback123 ebgp_multihop: 3 - route_map_in: RM-123-1-1-11-IN route_map_out: RM-123-1-1-11-OUT + route_map_in: RM-123-1-1-11-IN local_as: '123' - ip_address: fd5a:fe45:8831:06c5::a remote_as: '12345' @@ -245,15 +245,15 @@ static_routes: gateway: 1.2.3.4 vrf: Tenant_A_WAN_Zone - destination_address_prefix: 1.1.1.0/24 - interface: vlan101 gateway: 10.1.1.1 + interface: vlan101 vrf: Tenant_A_WAN_Zone - destination_address_prefix: 1.1.2.0/24 - interface: vlan101 gateway: 10.1.1.1 distance: 200 tag: 666 name: RT-TO-FAKE-DMZ + interface: vlan101 vrf: Tenant_A_WAN_Zone - destination_address_prefix: 10.3.5.0/24 interface: Null0 @@ -452,14 +452,14 @@ ethernet_interfaces: shutdown: false - name: Ethernet4000 description: My second test - ip_address: 10.1.2.3/12 shutdown: false - switchport: - enabled: false mtu: 1500 + ip_address: 10.1.2.3/12 peer: MY-own-peer peer_interface: Ethernet123 peer_type: my_precious + switchport: + enabled: false loopback_interfaces: - name: Loopback0 description: CUSTOM_EVPN_Overlay_Peering_L3LEAF diff --git a/ansible_collections/arista/avd/molecule/evpn_underlay_rfc5549_overlay_ebgp/intended/structured_configs/DC1-BL1A.yml b/ansible_collections/arista/avd/molecule/evpn_underlay_rfc5549_overlay_ebgp/intended/structured_configs/DC1-BL1A.yml index e254f3dce77..f2a778ab621 100644 --- a/ansible_collections/arista/avd/molecule/evpn_underlay_rfc5549_overlay_ebgp/intended/structured_configs/DC1-BL1A.yml +++ b/ansible_collections/arista/avd/molecule/evpn_underlay_rfc5549_overlay_ebgp/intended/structured_configs/DC1-BL1A.yml @@ -370,14 +370,14 @@ ethernet_interfaces: description: P2P_outside-r1_other1 - name: Ethernet4000 description: My test - ip_address: 10.1.2.3/12 shutdown: false - switchport: - enabled: false mtu: 1500 + ip_address: 10.1.2.3/12 peer: MY-own-peer peer_interface: Ethernet123 peer_type: my_precious + switchport: + enabled: false loopback_interfaces: - name: Loopback0 description: ROUTER_ID diff --git a/ansible_collections/arista/avd/molecule/evpn_underlay_rfc5549_overlay_ebgp/intended/structured_configs/DC1-BL1B.yml b/ansible_collections/arista/avd/molecule/evpn_underlay_rfc5549_overlay_ebgp/intended/structured_configs/DC1-BL1B.yml index 9728aca1854..fb10bce51b7 100644 --- a/ansible_collections/arista/avd/molecule/evpn_underlay_rfc5549_overlay_ebgp/intended/structured_configs/DC1-BL1B.yml +++ b/ansible_collections/arista/avd/molecule/evpn_underlay_rfc5549_overlay_ebgp/intended/structured_configs/DC1-BL1B.yml @@ -371,14 +371,14 @@ ethernet_interfaces: description: P2P_outside-r1_other2 - name: Ethernet4000 description: My test - ip_address: 10.1.2.3/12 shutdown: false - switchport: - enabled: false mtu: 1500 + ip_address: 10.1.2.3/12 peer: MY-own-peer peer_interface: Ethernet123 peer_type: my_precious + switchport: + enabled: false loopback_interfaces: - name: Loopback0 description: ROUTER_ID diff --git a/ansible_collections/arista/avd/plugins/action/eos_designs_facts.py b/ansible_collections/arista/avd/plugins/action/eos_designs_facts.py index 5bc23ce559f..fb17f9df62f 100644 --- a/ansible_collections/arista/avd/plugins/action/eos_designs_facts.py +++ b/ansible_collections/arista/avd/plugins/action/eos_designs_facts.py @@ -18,10 +18,11 @@ try: from pyavd._eos_designs.eos_designs_facts import EosDesignsFacts + from pyavd._eos_designs.schema import EosDesigns from pyavd._eos_designs.shared_utils import SharedUtils from pyavd._errors import AristaAvdError except ImportError as e: - EosDesignsFacts = SharedUtils = RaiseOnUse( + EosDesignsFacts = EosDesigns = SharedUtils = RaiseOnUse( AnsibleActionFail( f"The '{PLUGIN_NAME}' plugin requires the 'pyavd' Python library. Got import error", orig_exc=e, @@ -159,11 +160,14 @@ def create_avd_switch_facts_instances(self, fabric_hosts: list, hostvars: object # This is used to access EosDesignsFacts objects of other switches during rendering of one switch. host_hostvars["avd_switch_facts"] = avd_switch_facts + # Load input vars into the EosDesigns data class. + inputs = EosDesigns._from_dict(host_hostvars, load_custom_structured_config=False) + # Initialize SharedUtils class to be passed to EosDesignsFacts below. - shared_utils = SharedUtils(hostvars=host_hostvars, templar=self.templar, schema=avdschematools.avdschema) + shared_utils = SharedUtils(hostvars=host_hostvars, inputs=inputs, templar=self.templar, schema=avdschematools.avdschema) # Create an instance of EosDesignsFacts and insert into common avd_switch_facts dict - avd_switch_facts[host] = {"switch": EosDesignsFacts(hostvars=host_hostvars, shared_utils=shared_utils)} + avd_switch_facts[host] = {"switch": EosDesignsFacts(hostvars=host_hostvars, inputs=inputs, shared_utils=shared_utils)} # Add "switch" as a reference to the newly created EosDesignsFacts instance directly in the hostvars # to allow `shared_utils` to work the same when they are called from `EosDesignsFacts` or from `AvdStructuredConfig`. diff --git a/ansible_collections/arista/avd/roles/eos_designs/docs/tables/network-services-vrfs-l3-interfaces-settings.md b/ansible_collections/arista/avd/roles/eos_designs/docs/tables/network-services-vrfs-l3-interfaces-settings.md index 65a29b4a1b1..081aa5f2c6b 100644 --- a/ansible_collections/arista/avd/roles/eos_designs/docs/tables/network-services-vrfs-l3-interfaces-settings.md +++ b/ansible_collections/arista/avd/roles/eos_designs/docs/tables/network-services-vrfs-l3-interfaces-settings.md @@ -23,7 +23,7 @@ | [            description](## ".[].vrfs.[].l3_interfaces.[].description") | String | | | | | | [            descriptions](## ".[].vrfs.[].l3_interfaces.[].descriptions") | List, items: String | | | | "descriptions" has precedence over "description".
| | [              - <str>](## ".[].vrfs.[].l3_interfaces.[].descriptions.[]") | String | | | | | - | [            enabled](## ".[].vrfs.[].l3_interfaces.[].enabled") | Boolean | | | | | + | [            enabled](## ".[].vrfs.[].l3_interfaces.[].enabled") | Boolean | | `True` | | | | [            mtu](## ".[].vrfs.[].l3_interfaces.[].mtu") | Integer | | | | | | [            ipv4_acl_in](## ".[].vrfs.[].l3_interfaces.[].ipv4_acl_in") | String | | | | | | [            ipv4_acl_out](## ".[].vrfs.[].l3_interfaces.[].ipv4_acl_out") | String | | | | | @@ -91,7 +91,7 @@ # "descriptions" has precedence over "description". descriptions: - - enabled: + enabled: mtu: ipv4_acl_in: ipv4_acl_out: diff --git a/ansible_collections/arista/avd/roles/eos_designs/docs/tables/network-services-vrfs-svis-settings.md b/ansible_collections/arista/avd/roles/eos_designs/docs/tables/network-services-vrfs-svis-settings.md index 509c70b01e0..f0ae98d485b 100644 --- a/ansible_collections/arista/avd/roles/eos_designs/docs/tables/network-services-vrfs-svis-settings.md +++ b/ansible_collections/arista/avd/roles/eos_designs/docs/tables/network-services-vrfs-svis-settings.md @@ -57,7 +57,7 @@ | [                raw_eos_cli](## ".[].vrfs.[].svis.[].nodes.[].raw_eos_cli") | String | | | | EOS CLI rendered directly on the VLAN interface in the final EOS configuration.
| | [                structured_config](## ".[].vrfs.[].svis.[].nodes.[].structured_config") | Dictionary | | | | Custom structured config added under vlan_interfaces.[name=] for eos_cli_config_gen.
| | [                ipv6_address_virtual](## ".[].vrfs.[].svis.[].nodes.[].ipv6_address_virtual") removed | String | | | | IPv6_address/Mask.
ipv6 address virtuals to configure VXLAN Anycast IP address (Optional).
This key was removed. Support was removed in AVD version 5.0.0. Use ipv6_address_virtuals instead. | - | [                evpn_l2_multi_domain](## ".[].vrfs.[].svis.[].nodes.[].evpn_l2_multi_domain") | Boolean | | | | Explicitly extend SVI to remote EVPN domains.
Overrides `[].evpn_l2_multi_domain` and `[].vrfs[].evpn_l2_multi_domain`.
Not supported in conjuction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`.
| + | [                evpn_l2_multi_domain](## ".[].vrfs.[].svis.[].nodes.[].evpn_l2_multi_domain") | Boolean | | | | Explicitly extend SVI to remote EVPN domains.
Overrides `[].evpn_l2_multi_domain` and `[].vrfs[].evpn_l2_multi_domain`.
Not supported in conjunction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`.
| | [            enabled](## ".[].vrfs.[].svis.[].enabled") | Boolean | | | | Enable or disable interface. | | [            description](## ".[].vrfs.[].svis.[].description") | String | | | | SVI description. By default set to VLAN name.
| | [            ip_address](## ".[].vrfs.[].svis.[].ip_address") | String | | | | IPv4_address/Mask. Usually set under "nodes" to have unique IPv4 addresses per node. | @@ -92,7 +92,7 @@ | [            raw_eos_cli](## ".[].vrfs.[].svis.[].raw_eos_cli") | String | | | | EOS CLI rendered directly on the VLAN interface in the final EOS configuration.
| | [            structured_config](## ".[].vrfs.[].svis.[].structured_config") | Dictionary | | | | Custom structured config added under vlan_interfaces.[name=] for eos_cli_config_gen.
| | [            ipv6_address_virtual](## ".[].vrfs.[].svis.[].ipv6_address_virtual") removed | String | | | | IPv6_address/Mask.
ipv6 address virtuals to configure VXLAN Anycast IP address (Optional).
This key was removed. Support was removed in AVD version 5.0.0. Use ipv6_address_virtuals instead. | - | [            evpn_l2_multi_domain](## ".[].vrfs.[].svis.[].evpn_l2_multi_domain") | Boolean | | | | Explicitly extend SVI to remote EVPN domains.
Overrides `[].evpn_l2_multi_domain` and `[].vrfs[].evpn_l2_multi_domain`.
Not supported in conjuction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`.
| + | [            evpn_l2_multi_domain](## ".[].vrfs.[].svis.[].evpn_l2_multi_domain") | Boolean | | | | Explicitly extend SVI to remote EVPN domains.
Overrides `[].evpn_l2_multi_domain` and `[].vrfs[].evpn_l2_multi_domain`.
Not supported in conjunction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`.
| === "YAML" @@ -285,7 +285,7 @@ # Explicitly extend SVI to remote EVPN domains. # Overrides `[].evpn_l2_multi_domain` and `[].vrfs[].evpn_l2_multi_domain`. - # Not supported in conjuction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`. + # Not supported in conjunction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`. evpn_l2_multi_domain: # Enable or disable interface. @@ -413,6 +413,6 @@ # Explicitly extend SVI to remote EVPN domains. # Overrides `[].evpn_l2_multi_domain` and `[].vrfs[].evpn_l2_multi_domain`. - # Not supported in conjuction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`. + # Not supported in conjunction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`. evpn_l2_multi_domain: ``` 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/ansible_collections/arista/avd/roles/eos_designs/docs/tables/svi-profiles.md b/ansible_collections/arista/avd/roles/eos_designs/docs/tables/svi-profiles.md index e0f91575171..0df62ccf99f 100644 --- a/ansible_collections/arista/avd/roles/eos_designs/docs/tables/svi-profiles.md +++ b/ansible_collections/arista/avd/roles/eos_designs/docs/tables/svi-profiles.md @@ -47,7 +47,7 @@ | [        raw_eos_cli](## "svi_profiles.[].nodes.[].raw_eos_cli") | String | | | | EOS CLI rendered directly on the VLAN interface in the final EOS configuration.
| | [        structured_config](## "svi_profiles.[].nodes.[].structured_config") | Dictionary | | | | Custom structured config added under vlan_interfaces.[name=] for eos_cli_config_gen.
| | [        ipv6_address_virtual](## "svi_profiles.[].nodes.[].ipv6_address_virtual") removed | String | | | | IPv6_address/Mask.
ipv6 address virtuals to configure VXLAN Anycast IP address (Optional).
This key was removed. Support was removed in AVD version 5.0.0. Use ipv6_address_virtuals instead. | - | [        evpn_l2_multi_domain](## "svi_profiles.[].nodes.[].evpn_l2_multi_domain") | Boolean | | | | Explicitly extend SVI to remote EVPN domains.
Overrides `[].evpn_l2_multi_domain` and `[].vrfs[].evpn_l2_multi_domain`.
Not supported in conjuction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`.
| + | [        evpn_l2_multi_domain](## "svi_profiles.[].nodes.[].evpn_l2_multi_domain") | Boolean | | | | Explicitly extend SVI to remote EVPN domains.
Overrides `[].evpn_l2_multi_domain` and `[].vrfs[].evpn_l2_multi_domain`.
Not supported in conjunction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`.
| | [    name](## "svi_profiles.[].name") | String | | | | VLAN name. | | [    enabled](## "svi_profiles.[].enabled") | Boolean | | | | Enable or disable interface. | | [    description](## "svi_profiles.[].description") | String | | | | SVI description. By default set to VLAN name.
| @@ -83,7 +83,7 @@ | [    raw_eos_cli](## "svi_profiles.[].raw_eos_cli") | String | | | | EOS CLI rendered directly on the VLAN interface in the final EOS configuration.
| | [    structured_config](## "svi_profiles.[].structured_config") | Dictionary | | | | Custom structured config added under vlan_interfaces.[name=] for eos_cli_config_gen.
| | [    ipv6_address_virtual](## "svi_profiles.[].ipv6_address_virtual") removed | String | | | | IPv6_address/Mask.
ipv6 address virtuals to configure VXLAN Anycast IP address (Optional).
This key was removed. Support was removed in AVD version 5.0.0. Use ipv6_address_virtuals instead. | - | [    evpn_l2_multi_domain](## "svi_profiles.[].evpn_l2_multi_domain") | Boolean | | | | Explicitly extend SVI to remote EVPN domains.
Overrides `[].evpn_l2_multi_domain` and `[].vrfs[].evpn_l2_multi_domain`.
Not supported in conjuction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`.
| + | [    evpn_l2_multi_domain](## "svi_profiles.[].evpn_l2_multi_domain") | Boolean | | | | Explicitly extend SVI to remote EVPN domains.
Overrides `[].evpn_l2_multi_domain` and `[].vrfs[].evpn_l2_multi_domain`.
Not supported in conjunction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`.
| === "YAML" @@ -241,7 +241,7 @@ # Explicitly extend SVI to remote EVPN domains. # Overrides `[].evpn_l2_multi_domain` and `[].vrfs[].evpn_l2_multi_domain`. - # Not supported in conjuction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`. + # Not supported in conjunction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`. evpn_l2_multi_domain: # VLAN name. @@ -372,6 +372,6 @@ # Explicitly extend SVI to remote EVPN domains. # Overrides `[].evpn_l2_multi_domain` and `[].vrfs[].evpn_l2_multi_domain`. - # Not supported in conjuction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`. + # Not supported in conjunction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`. evpn_l2_multi_domain: ``` diff --git a/pylintrc b/pylintrc index e303d44f9b7..1ea56f6060d 100644 --- a/pylintrc +++ b/pylintrc @@ -3,7 +3,10 @@ ignore-paths= # We will Pylint for ansible_collections separately since it uses it's own pylintrc in the collection root. ansible_collections, # The cv_client api is generated from proto files, so it should not be linted. - python-avd/pyavd/_cv/api + python-avd/pyavd/_cv/api, + # The schema/__init__.py are generated, so they should not be linted. + python-avd/pyavd/_eos_cli_config_gen/schema/__init__.py, + python-avd/pyavd/_eos_designs/schema/__init__.py, [MESSAGES CONTROL] disable= diff --git a/pyproject.toml b/pyproject.toml index dd21ae7a02f..ba69d6b4ee8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,19 +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/.*''' +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 @@ -78,6 +71,25 @@ convention = "google" "python-avd/pyavd/_cv/client/*.py" = [ "B904", # Within an `except` clause, raise exceptions with `raise - TODO: Improve code ] +"python-avd/pyavd/_eos_cli_config_gen/schema/__init__.py" = [ + "A002", # Argument is shadowing a Python builtin - OK since these are data classes + "PLR0913", # Too many arguments in function definition - OK since these are data classes + "N803", # Argument name should be lowercase - TODO AVD6.0.0 can be removed when Vxlan1 is gone. + "N815", # Variable in class scope should not be mixedCase - TODO AVD6.0.0 can be removed when Vxlan1 is gone. + "E501", # Line too long - OK since we may have some very long vars or deeply nested with a long one-line description. + "S107", # Possible hardcoded password assigned to function default - False positive. + "F811", # Redefinition of unused `Vxlan1` from line 45778 - TODO AVD6.0.0 can be removed when Vxlan1 is gone. + "D205", # 1 blank line required between summary line and description - OK since descriptions are autogenerated and for data fields. +] +"python-avd/pyavd/_eos_designs/schema/__init__.py" = [ + "A002", # Argument is shadowing a Python builtin - OK since these are data classes + "PLR0913", # Too many arguments in function definition - OK since these are data classes + "N803", # Argument name should be lowercase - TODO AVD6.0.0 can be removed when Vxlan1 is gone. + "E501", # Line too long - OK since we may have some very long vars or deeply nested with a long one-line description. + "S107", # Possible hardcoded password assigned to function default - False positive. + "S104", # Possible binding to all interfaces - False positive. + "D205", # 1 blank line required between summary line and description - OK since descriptions are autogenerated and for data fields. +] "python-avd/tests/**/*" = [ "S101", # Accept 'assert' in pytest. "INP001", # implicit namespace package. Add an `__init__.py` - Tests are not in packages diff --git a/python-avd/pyavd/_eos_cli_config_gen/schema/__init__.py b/python-avd/pyavd/_eos_cli_config_gen/schema/__init__.py new file mode 100644 index 00000000000..fc484a76cfc --- /dev/null +++ b/python-avd/pyavd/_eos_cli_config_gen/schema/__init__.py @@ -0,0 +1,68849 @@ +# Copyright (c) 2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, ClassVar, Literal + +from pyavd._schema.models.avd_indexed_list import AvdIndexedList +from pyavd._schema.models.avd_list import AvdList +from pyavd._schema.models.avd_model import AvdModel +from pyavd._schema.models.eos_cli_config_gen_root_model import EosCliConfigGenRootModel + +if TYPE_CHECKING: + from pyavd._utils import Undefined, UndefinedType + + +class EosCliConfigGen(EosCliConfigGenRootModel): + """Subclass of AvdModel.""" + + class AaaAccounting(AvdModel): + """Subclass of AvdModel.""" + + class Exec(AvdModel): + """Subclass of AvdModel.""" + + class Console(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"type": {"type": str}, "group": {"type": str}, "logging": {"type": bool}, "_custom_data": {"type": dict}} + type: Literal["none", "start-stop", "stop-only"] | None + group: str | None + """Group Name.""" + logging: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + type: Literal["none", "start-stop", "stop-only"] | None | UndefinedType = Undefined, + group: str | None | UndefinedType = Undefined, + logging: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Console. + + + Subclass of AvdModel. + + Args: + type: type + group: Group Name. + logging: logging + _custom_data: _custom_data + + """ + + class Default(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"type": {"type": str}, "group": {"type": str}, "logging": {"type": bool}, "_custom_data": {"type": dict}} + type: Literal["none", "start-stop", "stop-only"] | None + group: str | None + """Group Name.""" + logging: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + type: Literal["none", "start-stop", "stop-only"] | None | UndefinedType = Undefined, + group: str | None | UndefinedType = Undefined, + logging: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Default. + + + Subclass of AvdModel. + + Args: + type: type + group: Group Name. + logging: logging + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"console": {"type": Console}, "default": {"type": Default}, "_custom_data": {"type": dict}} + console: Console + """Subclass of AvdModel.""" + default: Default + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + console: Console | UndefinedType = Undefined, + default: Default | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Exec. + + + Subclass of AvdModel. + + Args: + console: Subclass of AvdModel. + default: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class System(AvdModel): + """Subclass of AvdModel.""" + + class Default(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"type": {"type": str}, "group": {"type": str}, "_custom_data": {"type": dict}} + type: Literal["none", "start-stop", "stop-only"] | None + group: str | None + """Group Name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + type: Literal["none", "start-stop", "stop-only"] | None | UndefinedType = Undefined, + group: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Default. + + + Subclass of AvdModel. + + Args: + type: type + group: Group Name. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"default": {"type": Default}, "_custom_data": {"type": dict}} + default: Default + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, default: Default | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + System. + + + Subclass of AvdModel. + + Args: + default: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Dot1x(AvdModel): + """Subclass of AvdModel.""" + + class Default(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"type": {"type": str}, "group": {"type": str}, "_custom_data": {"type": dict}} + type: Literal["start-stop", "stop-only"] | None + group: str | None + """Group Name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + type: Literal["start-stop", "stop-only"] | None | UndefinedType = Undefined, + group: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Default. + + + Subclass of AvdModel. + + Args: + type: type + group: Group Name. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"default": {"type": Default}, "_custom_data": {"type": dict}} + default: Default + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, default: Default | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Dot1x. + + + Subclass of AvdModel. + + Args: + default: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Commands(AvdModel): + """Subclass of AvdModel.""" + + class ConsoleItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "commands": {"type": str}, + "type": {"type": str}, + "group": {"type": str}, + "logging": {"type": bool}, + "_custom_data": {"type": dict}, + } + commands: str | None + """Privilege level 'all' or 0-15.""" + type: Literal["none", "start-stop", "stop-only"] | None + group: str | None + """Group Name.""" + logging: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + commands: str | None | UndefinedType = Undefined, + type: Literal["none", "start-stop", "stop-only"] | None | UndefinedType = Undefined, + group: str | None | UndefinedType = Undefined, + logging: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ConsoleItem. + + + Subclass of AvdModel. + + Args: + commands: Privilege level 'all' or 0-15. + type: type + group: Group Name. + logging: logging + _custom_data: _custom_data + + """ + + class Console(AvdList[ConsoleItem]): + """Subclass of AvdList with `ConsoleItem` items.""" + + Console._item_type = ConsoleItem + + class DefaultItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "commands": {"type": str}, + "type": {"type": str}, + "group": {"type": str}, + "logging": {"type": bool}, + "_custom_data": {"type": dict}, + } + commands: str | None + """Privilege level 'all' or 0-15.""" + type: Literal["none", "start-stop", "stop-only"] | None + group: str | None + """Group Name.""" + logging: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + commands: str | None | UndefinedType = Undefined, + type: Literal["none", "start-stop", "stop-only"] | None | UndefinedType = Undefined, + group: str | None | UndefinedType = Undefined, + logging: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultItem. + + + Subclass of AvdModel. + + Args: + commands: Privilege level 'all' or 0-15. + type: type + group: Group Name. + logging: logging + _custom_data: _custom_data + + """ + + class Default(AvdList[DefaultItem]): + """Subclass of AvdList with `DefaultItem` items.""" + + Default._item_type = DefaultItem + + _fields: ClassVar[dict] = {"console": {"type": Console}, "default": {"type": Default}, "_custom_data": {"type": dict}} + console: Console + """Subclass of AvdList with `ConsoleItem` items.""" + default: Default + """Subclass of AvdList with `DefaultItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + console: Console | UndefinedType = Undefined, + default: Default | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Commands. + + + Subclass of AvdModel. + + Args: + console: Subclass of AvdList with `ConsoleItem` items. + default: Subclass of AvdList with `DefaultItem` items. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "exec": {"type": Exec}, + "system": {"type": System}, + "dot1x": {"type": Dot1x}, + "commands": {"type": Commands}, + "_custom_data": {"type": dict}, + } + exec: Exec + """Subclass of AvdModel.""" + system: System + """Subclass of AvdModel.""" + dot1x: Dot1x + """Subclass of AvdModel.""" + commands: Commands + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + exec: Exec | UndefinedType = Undefined, + system: System | UndefinedType = Undefined, + dot1x: Dot1x | UndefinedType = Undefined, + commands: Commands | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AaaAccounting. + + + Subclass of AvdModel. + + Args: + exec: Subclass of AvdModel. + system: Subclass of AvdModel. + dot1x: Subclass of AvdModel. + commands: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class AaaAuthentication(AvdModel): + """Subclass of AvdModel.""" + + class Login(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"default": {"type": str}, "console": {"type": str}, "_custom_data": {"type": dict}} + default: str | None + """ + Login authentication method(s) as a string. + Examples: + - "group tacacs+ local" + - "group MYGROUP none" + - "group radius group MYGROUP local" + """ + console: str | None + """ + Console authentication method(s) as a string. + Examples: + - "group tacacs+ local" + - "group MYGROUP + none" + - "group radius group MYGROUP local" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + default: str | None | UndefinedType = Undefined, + console: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Login. + + + Subclass of AvdModel. + + Args: + default: + Login authentication method(s) as a string. + Examples: # fmt: skip + - "group tacacs+ local" + - "group MYGROUP none" + - "group radius group MYGROUP local" + console: + Console authentication method(s) as a string. + Examples: # fmt: skip + - "group tacacs+ local" + - "group MYGROUP + none" + - "group radius group MYGROUP local" + _custom_data: _custom_data + + """ + + class Enable(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"default": {"type": str}, "_custom_data": {"type": dict}} + default: str | None + """ + Enable authentication method(s) as a string. + Examples: + - "group tacacs+ local" + - "group MYGROUP + none" + - "group radius group MYGROUP local" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, default: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Enable. + + + Subclass of AvdModel. + + Args: + default: + Enable authentication method(s) as a string. + Examples: # fmt: skip + - "group tacacs+ local" + - "group MYGROUP + none" + - "group radius group MYGROUP local" + _custom_data: _custom_data + + """ + + class Dot1x(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"default": {"type": str}, "_custom_data": {"type": dict}} + default: str | None + """ + 802.1x authentication method(s) as a string. + Examples: + - "group radius" + - "group MYGROUP group + radius" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, default: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Dot1x. + + + Subclass of AvdModel. + + Args: + default: + 802.1x authentication method(s) as a string. + Examples: # fmt: skip + - "group radius" + - "group MYGROUP group + radius" + _custom_data: _custom_data + + """ + + class Policies(AvdModel): + """Subclass of AvdModel.""" + + class Local(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"allow_nopassword": {"type": bool}, "_custom_data": {"type": dict}} + allow_nopassword: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, allow_nopassword: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Local. + + + Subclass of AvdModel. + + Args: + allow_nopassword: allow_nopassword + _custom_data: _custom_data + + """ + + class Lockout(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"failure": {"type": int}, "duration": {"type": int}, "window": {"type": int}, "_custom_data": {"type": dict}} + failure: int | None + duration: int | None + window: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + failure: int | None | UndefinedType = Undefined, + duration: int | None | UndefinedType = Undefined, + window: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Lockout. + + + Subclass of AvdModel. + + Args: + failure: failure + duration: duration + window: window + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "on_failure_log": {"type": bool}, + "on_success_log": {"type": bool}, + "local": {"type": Local}, + "lockout": {"type": Lockout}, + "_custom_data": {"type": dict}, + } + on_failure_log: bool | None + on_success_log: bool | None + local: Local + """Subclass of AvdModel.""" + lockout: Lockout + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + on_failure_log: bool | None | UndefinedType = Undefined, + on_success_log: bool | None | UndefinedType = Undefined, + local: Local | UndefinedType = Undefined, + lockout: Lockout | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Policies. + + + Subclass of AvdModel. + + Args: + on_failure_log: on_failure_log + on_success_log: on_success_log + local: Subclass of AvdModel. + lockout: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "login": {"type": Login}, + "enable": {"type": Enable}, + "dot1x": {"type": Dot1x}, + "policies": {"type": Policies}, + "_custom_data": {"type": dict}, + } + login: Login + """Subclass of AvdModel.""" + enable: Enable + """Subclass of AvdModel.""" + dot1x: Dot1x + """Subclass of AvdModel.""" + policies: Policies + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + login: Login | UndefinedType = Undefined, + enable: Enable | UndefinedType = Undefined, + dot1x: Dot1x | UndefinedType = Undefined, + policies: Policies | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AaaAuthentication. + + + Subclass of AvdModel. + + Args: + login: Subclass of AvdModel. + enable: Subclass of AvdModel. + dot1x: Subclass of AvdModel. + policies: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class AaaAuthorization(AvdModel): + """Subclass of AvdModel.""" + + class Policy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"local_default_role": {"type": str}, "_custom_data": {"type": dict}} + local_default_role: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, local_default_role: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Policy. + + + Subclass of AvdModel. + + Args: + local_default_role: local_default_role + _custom_data: _custom_data + + """ + + class Exec(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"default": {"type": str}, "_custom_data": {"type": dict}} + default: str | None + """ + Exec authorization method(s) as a string. + Examples: + - "group tacacs+ local" + - "group MYGROUP none" + - + "group radius group MYGROUP local" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, default: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Exec. + + + Subclass of AvdModel. + + Args: + default: + Exec authorization method(s) as a string. + Examples: # fmt: skip + - "group tacacs+ local" + - "group MYGROUP none" + - + "group radius group MYGROUP local" + _custom_data: _custom_data + + """ + + class Dynamic(AvdModel): + """Subclass of AvdModel.""" + + class Dot1xAdditionalGroups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Dot1xAdditionalGroups._item_type = str + + _fields: ClassVar[dict] = {"dot1x_additional_groups": {"type": Dot1xAdditionalGroups}, "_custom_data": {"type": dict}} + dot1x_additional_groups: Dot1xAdditionalGroups + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dot1x_additional_groups: Dot1xAdditionalGroups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dynamic. + + + Subclass of AvdModel. + + Args: + dot1x_additional_groups: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class Commands(AvdModel): + """Subclass of AvdModel.""" + + class PrivilegeItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "default": {"type": str}, "_custom_data": {"type": dict}} + level: str | None + """Privilege level(s) 0-15.""" + default: str | None + """ + Command authorization method(s) as a string. + Examples: + - "group tacacs+ local" + - "group MYGROUP + none" + - "group tacacs+ group MYGROUP local" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + default: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PrivilegeItem. + + + Subclass of AvdModel. + + Args: + level: Privilege level(s) 0-15. + default: + Command authorization method(s) as a string. + Examples: # fmt: skip + - "group tacacs+ local" + - "group MYGROUP + none" + - "group tacacs+ group MYGROUP local" + _custom_data: _custom_data + + """ + + class Privilege(AvdList[PrivilegeItem]): + """Subclass of AvdList with `PrivilegeItem` items.""" + + Privilege._item_type = PrivilegeItem + + _fields: ClassVar[dict] = {"all_default": {"type": str}, "privilege": {"type": Privilege}, "_custom_data": {"type": dict}} + all_default: str | None + """ + Command authorization method(s) as a string. + Examples: + - "group tacacs+ local" + - "group MYGROUP + none" + - "group tacacs+ group MYGROUP local + """ + privilege: Privilege + """Subclass of AvdList with `PrivilegeItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + all_default: str | None | UndefinedType = Undefined, + privilege: Privilege | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Commands. + + + Subclass of AvdModel. + + Args: + all_default: + Command authorization method(s) as a string. + Examples: # fmt: skip + - "group tacacs+ local" + - "group MYGROUP + none" + - "group tacacs+ group MYGROUP local + privilege: Subclass of AvdList with `PrivilegeItem` items. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "policy": {"type": Policy}, + "exec": {"type": Exec}, + "config_commands": {"type": bool}, + "serial_console": {"type": bool}, + "dynamic": {"type": Dynamic}, + "commands": {"type": Commands}, + "_custom_data": {"type": dict}, + } + policy: Policy + """Subclass of AvdModel.""" + exec: Exec + """Subclass of AvdModel.""" + config_commands: bool | None + serial_console: bool | None + dynamic: Dynamic + """Subclass of AvdModel.""" + commands: Commands + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + policy: Policy | UndefinedType = Undefined, + exec: Exec | UndefinedType = Undefined, + config_commands: bool | None | UndefinedType = Undefined, + serial_console: bool | None | UndefinedType = Undefined, + dynamic: Dynamic | UndefinedType = Undefined, + commands: Commands | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AaaAuthorization. + + + Subclass of AvdModel. + + Args: + policy: Subclass of AvdModel. + exec: Subclass of AvdModel. + config_commands: config_commands + serial_console: serial_console + dynamic: Subclass of AvdModel. + commands: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class AaaRoot(AvdModel): + """Subclass of AvdModel.""" + + class Secret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"sha512_password": {"type": str}, "_custom_data": {"type": dict}} + sha512_password: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, sha512_password: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Secret. + + + Subclass of AvdModel. + + Args: + sha512_password: sha512_password + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"disabled": {"type": bool}, "secret": {"type": Secret}, "_custom_data": {"type": dict}} + disabled: bool | None + """Set to `true` to configure `no aaa root` which is the EOS default.""" + secret: Secret + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + disabled: bool | None | UndefinedType = Undefined, + secret: Secret | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AaaRoot. + + + Subclass of AvdModel. + + Args: + disabled: Set to `true` to configure `no aaa root` which is the EOS default. + secret: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class AaaServerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class ServersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"server": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + server: str | None + """Hostname or IP address.""" + vrf: str | None + """VRF name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + server: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ServersItem. + + + Subclass of AvdModel. + + Args: + server: Hostname or IP address. + vrf: VRF name. + _custom_data: _custom_data + + """ + + class Servers(AvdList[ServersItem]): + """Subclass of AvdList with `ServersItem` items.""" + + Servers._item_type = ServersItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "type": {"type": str}, "servers": {"type": Servers}, "_custom_data": {"type": dict}} + name: str + """Group name.""" + type: Literal["tacacs+", "radius", "ldap"] | None + servers: Servers + """Subclass of AvdList with `ServersItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + type: Literal["tacacs+", "radius", "ldap"] | None | UndefinedType = Undefined, + servers: Servers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AaaServerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Group name. + type: type + servers: Subclass of AvdList with `ServersItem` items. + _custom_data: _custom_data + + """ + + class AaaServerGroups(AvdIndexedList[str, AaaServerGroupsItem]): + """Subclass of AvdIndexedList with `AaaServerGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + AaaServerGroups._item_type = AaaServerGroupsItem + + class AccessListsItem(AvdModel): + """Subclass of AvdModel.""" + + class SequenceNumbersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"sequence": {"type": int}, "action": {"type": str}, "_custom_data": {"type": dict}} + sequence: int + """Sequence ID.""" + action: str + """ + Action as string. + Example: "deny ip any any" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sequence: int | UndefinedType = Undefined, + action: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceNumbersItem. + + + Subclass of AvdModel. + + Args: + sequence: Sequence ID. + action: + Action as string. + Example: "deny ip any any" + _custom_data: _custom_data + + """ + + class SequenceNumbers(AvdIndexedList[int, SequenceNumbersItem]): + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + + _primary_key: ClassVar[str] = "sequence" + + SequenceNumbers._item_type = SequenceNumbersItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "counters_per_entry": {"type": bool}, + "permit_response_traffic": {"type": str}, + "sequence_numbers": {"type": SequenceNumbers}, + "_custom_data": {"type": dict}, + } + name: str + """Access-list Name.""" + counters_per_entry: bool | None + permit_response_traffic: Literal["nat"] | None + """ + Permit response traffic automatically based on NAT translations. + Minimum EOS version requirement + 4.32.2F. + """ + sequence_numbers: SequenceNumbers + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + counters_per_entry: bool | None | UndefinedType = Undefined, + permit_response_traffic: Literal["nat"] | None | UndefinedType = Undefined, + sequence_numbers: SequenceNumbers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AccessListsItem. + + + Subclass of AvdModel. + + Args: + name: Access-list Name. + counters_per_entry: counters_per_entry + permit_response_traffic: + Permit response traffic automatically based on NAT translations. + Minimum EOS version requirement + 4.32.2F. + sequence_numbers: Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`). + _custom_data: _custom_data + + """ + + class AccessLists(AvdIndexedList[str, AccessListsItem]): + """Subclass of AvdIndexedList with `AccessListsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + AccessLists._item_type = AccessListsItem + + class AddressLocking(AvdModel): + """Subclass of AvdModel.""" + + class DhcpServersIpv4(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DhcpServersIpv4._item_type = str + + class LeasesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ip": {"type": str}, "mac": {"type": str}, "_custom_data": {"type": dict}} + ip: str + """IP address.""" + mac: str + """MAC address (hhhh.hhhh.hhhh or hh:hh:hh:hh:hh:hh).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, ip: str | UndefinedType = Undefined, mac: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + LeasesItem. + + + Subclass of AvdModel. + + Args: + ip: IP address. + mac: MAC address (hhhh.hhhh.hhhh or hh:hh:hh:hh:hh:hh). + _custom_data: _custom_data + + """ + + class Leases(AvdList[LeasesItem]): + """Subclass of AvdList with `LeasesItem` items.""" + + Leases._item_type = LeasesItem + + class LockedAddress(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "expiration_mac_disabled": {"type": bool}, + "ipv4_enforcement_disabled": {"type": bool}, + "ipv6_enforcement_disabled": {"type": bool}, + "_custom_data": {"type": dict}, + } + expiration_mac_disabled: bool | None + """Configure deauthorizing locked addresses upon MAC aging out.""" + ipv4_enforcement_disabled: bool | None + """Configure enforcement for locked IPv4 addresses.""" + ipv6_enforcement_disabled: bool | None + """Configure enforcement for locked IPv6 addresses.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + expiration_mac_disabled: bool | None | UndefinedType = Undefined, + ipv4_enforcement_disabled: bool | None | UndefinedType = Undefined, + ipv6_enforcement_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LockedAddress. + + + Subclass of AvdModel. + + Args: + expiration_mac_disabled: Configure deauthorizing locked addresses upon MAC aging out. + ipv4_enforcement_disabled: Configure enforcement for locked IPv4 addresses. + ipv6_enforcement_disabled: Configure enforcement for locked IPv6 addresses. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "dhcp_servers_ipv4": {"type": DhcpServersIpv4}, + "disabled": {"type": bool}, + "leases": {"type": Leases}, + "local_interface": {"type": str}, + "locked_address": {"type": LockedAddress}, + "_custom_data": {"type": dict}, + } + dhcp_servers_ipv4: DhcpServersIpv4 + """Subclass of AvdList with `str` items.""" + disabled: bool | None + """Disable IP locking on configured ports.""" + leases: Leases + """Subclass of AvdList with `LeasesItem` items.""" + local_interface: str | None + locked_address: LockedAddress + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dhcp_servers_ipv4: DhcpServersIpv4 | UndefinedType = Undefined, + disabled: bool | None | UndefinedType = Undefined, + leases: Leases | UndefinedType = Undefined, + local_interface: str | None | UndefinedType = Undefined, + locked_address: LockedAddress | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressLocking. + + + Subclass of AvdModel. + + Args: + dhcp_servers_ipv4: Subclass of AvdList with `str` items. + disabled: Disable IP locking on configured ports. + leases: Subclass of AvdList with `LeasesItem` items. + local_interface: local_interface + locked_address: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class AgentsItem(AvdModel): + """Subclass of AvdModel.""" + + class EnvironmentVariablesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "value": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Environment variable name.""" + value: str + """Environment variable value.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + value: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EnvironmentVariablesItem. + + + Subclass of AvdModel. + + Args: + name: Environment variable name. + value: Environment variable value. + _custom_data: _custom_data + + """ + + class EnvironmentVariables(AvdIndexedList[str, EnvironmentVariablesItem]): + """Subclass of AvdIndexedList with `EnvironmentVariablesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + EnvironmentVariables._item_type = EnvironmentVariablesItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "environment_variables": {"type": EnvironmentVariables}, "_custom_data": {"type": dict}} + name: str + """Agent name.""" + environment_variables: EnvironmentVariables + """Subclass of AvdIndexedList with `EnvironmentVariablesItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + environment_variables: EnvironmentVariables | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AgentsItem. + + + Subclass of AvdModel. + + Args: + name: Agent name. + environment_variables: Subclass of AvdIndexedList with `EnvironmentVariablesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class Agents(AvdIndexedList[str, AgentsItem]): + """Subclass of AvdIndexedList with `AgentsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Agents._item_type = AgentsItem + + class ApplicationTrafficRecognition(AvdModel): + """Subclass of AvdModel.""" + + class CategoriesItem(AvdModel): + """Subclass of AvdModel.""" + + class ApplicationsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "service": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + """Application name.""" + service: Literal["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"] | None + """ + Service Name. + Specific service to target for this application. + If no service is specified, all + supported services of the application are matched. + Not all valid values are valid for all + applications, check on EOS CLI. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + service: Literal["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"] + | None + | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ApplicationsItem. + + + Subclass of AvdModel. + + Args: + name: Application name. + service: + Service Name. + Specific service to target for this application. + If no service is specified, all + supported services of the application are matched. + Not all valid values are valid for all + applications, check on EOS CLI. + _custom_data: _custom_data + + """ + + class Applications(AvdList[ApplicationsItem]): + """Subclass of AvdList with `ApplicationsItem` items.""" + + Applications._item_type = ApplicationsItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "applications": {"type": Applications}, "_custom_data": {"type": dict}} + name: str + """Category name.""" + applications: Applications + """ + List of applications. + + Subclass of AvdList with `ApplicationsItem` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + applications: Applications | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CategoriesItem. + + + Subclass of AvdModel. + + Args: + name: Category name. + applications: + List of applications. + + Subclass of AvdList with `ApplicationsItem` items. + _custom_data: _custom_data + + """ + + class Categories(AvdIndexedList[str, CategoriesItem]): + """Subclass of AvdIndexedList with `CategoriesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Categories._item_type = CategoriesItem + + class FieldSets(AvdModel): + """Subclass of AvdModel.""" + + class L4PortsItem(AvdModel): + """Subclass of AvdModel.""" + + class PortValues(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + PortValues._item_type = str + + _fields: ClassVar[dict] = {"name": {"type": str}, "port_values": {"type": PortValues}, "_custom_data": {"type": dict}} + name: str + """L4 port field-set name.""" + port_values: PortValues + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + port_values: PortValues | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L4PortsItem. + + + Subclass of AvdModel. + + Args: + name: L4 port field-set name. + port_values: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class L4Ports(AvdIndexedList[str, L4PortsItem]): + """Subclass of AvdIndexedList with `L4PortsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + L4Ports._item_type = L4PortsItem + + class Ipv4PrefixesItem(AvdModel): + """Subclass of AvdModel.""" + + class PrefixValues(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + PrefixValues._item_type = str + + _fields: ClassVar[dict] = {"name": {"type": str}, "prefix_values": {"type": PrefixValues}, "_custom_data": {"type": dict}} + name: str + """IPv4 prefix field-set name.""" + prefix_values: PrefixValues + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + prefix_values: PrefixValues | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4PrefixesItem. + + + Subclass of AvdModel. + + Args: + name: IPv4 prefix field-set name. + prefix_values: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class Ipv4Prefixes(AvdIndexedList[str, Ipv4PrefixesItem]): + """Subclass of AvdIndexedList with `Ipv4PrefixesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Ipv4Prefixes._item_type = Ipv4PrefixesItem + + _fields: ClassVar[dict] = {"l4_ports": {"type": L4Ports}, "ipv4_prefixes": {"type": Ipv4Prefixes}, "_custom_data": {"type": dict}} + l4_ports: L4Ports + """ + L4 port field-set. + + Subclass of AvdIndexedList with `L4PortsItem` items. Primary key is `name` + (`str`). + """ + ipv4_prefixes: Ipv4Prefixes + """ + IPv4 prefix field set. + + Subclass of AvdIndexedList with `Ipv4PrefixesItem` items. Primary key is + `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + l4_ports: L4Ports | UndefinedType = Undefined, + ipv4_prefixes: Ipv4Prefixes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FieldSets. + + + Subclass of AvdModel. + + Args: + l4_ports: + L4 port field-set. + + Subclass of AvdIndexedList with `L4PortsItem` items. Primary key is `name` + (`str`). + ipv4_prefixes: + IPv4 prefix field set. + + Subclass of AvdIndexedList with `Ipv4PrefixesItem` items. Primary key is + `name` (`str`). + _custom_data: _custom_data + + """ + + class Applications(AvdModel): + """Subclass of AvdModel.""" + + class Ipv4ApplicationsItem(AvdModel): + """Subclass of AvdModel.""" + + class DscpRanges(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DscpRanges._item_type = str + + class Protocols(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Protocols._item_type = str + + class ProtocolRanges(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + ProtocolRanges._item_type = str + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "src_prefix_set_name": {"type": str}, + "dest_prefix_set_name": {"type": str}, + "dscp_ranges": {"type": DscpRanges}, + "protocols": {"type": Protocols}, + "protocol_ranges": {"type": ProtocolRanges}, + "udp_src_port_set_name": {"type": str}, + "tcp_src_port_set_name": {"type": str}, + "udp_dest_port_set_name": {"type": str}, + "tcp_dest_port_set_name": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Application name.""" + src_prefix_set_name: str | None + """Source prefix set name.""" + dest_prefix_set_name: str | None + """Destination prefix set name.""" + dscp_ranges: DscpRanges + """ + Accept DSCP value(s) or range(s). + DSCP values can be between 0 and 63. + Other valid values are cs0 to + cs7, af11-13, af21-23, af31-33, af41-af43 and ef. + Note: The values are not sorted so the list items + need to be supplied in the right order to match the CLI if required. + + Subclass of AvdList with `str` + items. + """ + protocols: Protocols + """ + List of protocols to consider for this application. + To use port field-sets (source, destination or + both), the list + must contain only one or two protocols, either `tcp` or `udp`. + When using both + protocols, one line is rendered for each in the configuration, + hence the field-sets must have the + same value for `tcp_src_port_set_name` and + `udp_src_port_set_name` and for `tcp_dest_port_set_name` + and `udp_dest_port_set_name` + if set in order to generate valid configuration in EOS. + + Subclass of + AvdList with `str` items. + """ + protocol_ranges: ProtocolRanges + """ + Accept protocol value(s) or range(s). + Protocol values can be between 1 and 255. + + Subclass of AvdList + with `str` items. + """ + udp_src_port_set_name: str | None + """ + Name of field set for UDP source ports. + When the `protocols` list contain both `tcp` and `udp`, this + key value + must be the same as `tcp_src_port_set_name`. + """ + tcp_src_port_set_name: str | None + """ + Name of field set for TCP source ports. + When the `protocols` list contain both `tcp` and `udp`, this + key value + must be the same as `udp_src_port_set_name`. + """ + udp_dest_port_set_name: str | None + """ + Name of field set for UDP destination ports. + When the `protocols` list contain both `tcp` and `udp`, + this key value + must be the same as `tcp_dest_port_set_name`. + """ + tcp_dest_port_set_name: str | None + """ + Name of field set for TCP destination ports. + When the `protocols` list contain both `tcp` and `udp`, + this key value + must be the same as `udp_dest_port_set_name`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + src_prefix_set_name: str | None | UndefinedType = Undefined, + dest_prefix_set_name: str | None | UndefinedType = Undefined, + dscp_ranges: DscpRanges | UndefinedType = Undefined, + protocols: Protocols | UndefinedType = Undefined, + protocol_ranges: ProtocolRanges | UndefinedType = Undefined, + udp_src_port_set_name: str | None | UndefinedType = Undefined, + tcp_src_port_set_name: str | None | UndefinedType = Undefined, + udp_dest_port_set_name: str | None | UndefinedType = Undefined, + tcp_dest_port_set_name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4ApplicationsItem. + + + Subclass of AvdModel. + + Args: + name: Application name. + src_prefix_set_name: Source prefix set name. + dest_prefix_set_name: Destination prefix set name. + dscp_ranges: + Accept DSCP value(s) or range(s). + DSCP values can be between 0 and 63. + Other valid values are cs0 to + cs7, af11-13, af21-23, af31-33, af41-af43 and ef. + Note: The values are not sorted so the list items + need to be supplied in the right order to match the CLI if required. + + Subclass of AvdList with `str` + items. + protocols: + List of protocols to consider for this application. + To use port field-sets (source, destination or + both), the list + must contain only one or two protocols, either `tcp` or `udp`. + When using both + protocols, one line is rendered for each in the configuration, + hence the field-sets must have the + same value for `tcp_src_port_set_name` and + `udp_src_port_set_name` and for `tcp_dest_port_set_name` + and `udp_dest_port_set_name` + if set in order to generate valid configuration in EOS. + + Subclass of + AvdList with `str` items. + protocol_ranges: + Accept protocol value(s) or range(s). + Protocol values can be between 1 and 255. + + Subclass of AvdList + with `str` items. + udp_src_port_set_name: + Name of field set for UDP source ports. + When the `protocols` list contain both `tcp` and `udp`, this + key value + must be the same as `tcp_src_port_set_name`. + tcp_src_port_set_name: + Name of field set for TCP source ports. + When the `protocols` list contain both `tcp` and `udp`, this + key value + must be the same as `udp_src_port_set_name`. + udp_dest_port_set_name: + Name of field set for UDP destination ports. + When the `protocols` list contain both `tcp` and `udp`, + this key value + must be the same as `tcp_dest_port_set_name`. + tcp_dest_port_set_name: + Name of field set for TCP destination ports. + When the `protocols` list contain both `tcp` and `udp`, + this key value + must be the same as `udp_dest_port_set_name`. + _custom_data: _custom_data + + """ + + class Ipv4Applications(AvdIndexedList[str, Ipv4ApplicationsItem]): + """Subclass of AvdIndexedList with `Ipv4ApplicationsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Ipv4Applications._item_type = Ipv4ApplicationsItem + + class L4ApplicationsItem(AvdModel): + """Subclass of AvdModel.""" + + class Protocols(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Protocols._item_type = str + + class ProtocolRanges(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + ProtocolRanges._item_type = str + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "protocols": {"type": Protocols}, + "protocol_ranges": {"type": ProtocolRanges}, + "udp_src_port_set_name": {"type": str}, + "tcp_src_port_set_name": {"type": str}, + "udp_dest_port_set_name": {"type": str}, + "tcp_dest_port_set_name": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Application name.""" + protocols: Protocols + """ + List of protocols to consider for this application. + To use port field-sets (source, destination or + both), the list + must contain only one or two protocols, either `tcp` or `udp`. + When using both + protocols, one line is rendered for each in the configuration, + hence the field-sets must have the + same value for `tcp_src_port_set_name` and + `udp_src_port_set_name` and for `tcp_dest_port_set_name` + and `udp_dest_port_set_name` + if set in order to generate valid configuration in EOS. + + Subclass of + AvdList with `str` items. + """ + protocol_ranges: ProtocolRanges + """ + Accept protocol value(s) or range(s). + Protocol values can be between 1 and 255. + + Subclass of AvdList + with `str` items. + """ + udp_src_port_set_name: str | None + """ + Name of field set for UDP source ports. + When the `protocols` list contain both `tcp` and `udp`, this + key value + must be the same as `tcp_src_port_set_name`. + """ + tcp_src_port_set_name: str | None + """ + Name of field set for TCP source ports. + When the `protocols` list contain both `tcp` and `udp`, this + key value + must be the same as `udp_src_port_set_name`. + """ + udp_dest_port_set_name: str | None + """ + Name of field set for UDP destination ports. + When the `protocols` list contain both `tcp` and `udp`, + this key value + must be the same as `tcp_dest_port_set_name`. + """ + tcp_dest_port_set_name: str | None + """ + Name of field set for TCP destination ports. + When the `protocols` list contain both `tcp` and `udp`, + this key value + must be the same as `udp_dest_port_set_name`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + protocols: Protocols | UndefinedType = Undefined, + protocol_ranges: ProtocolRanges | UndefinedType = Undefined, + udp_src_port_set_name: str | None | UndefinedType = Undefined, + tcp_src_port_set_name: str | None | UndefinedType = Undefined, + udp_dest_port_set_name: str | None | UndefinedType = Undefined, + tcp_dest_port_set_name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L4ApplicationsItem. + + + Subclass of AvdModel. + + Args: + name: Application name. + protocols: + List of protocols to consider for this application. + To use port field-sets (source, destination or + both), the list + must contain only one or two protocols, either `tcp` or `udp`. + When using both + protocols, one line is rendered for each in the configuration, + hence the field-sets must have the + same value for `tcp_src_port_set_name` and + `udp_src_port_set_name` and for `tcp_dest_port_set_name` + and `udp_dest_port_set_name` + if set in order to generate valid configuration in EOS. + + Subclass of + AvdList with `str` items. + protocol_ranges: + Accept protocol value(s) or range(s). + Protocol values can be between 1 and 255. + + Subclass of AvdList + with `str` items. + udp_src_port_set_name: + Name of field set for UDP source ports. + When the `protocols` list contain both `tcp` and `udp`, this + key value + must be the same as `tcp_src_port_set_name`. + tcp_src_port_set_name: + Name of field set for TCP source ports. + When the `protocols` list contain both `tcp` and `udp`, this + key value + must be the same as `udp_src_port_set_name`. + udp_dest_port_set_name: + Name of field set for UDP destination ports. + When the `protocols` list contain both `tcp` and `udp`, + this key value + must be the same as `tcp_dest_port_set_name`. + tcp_dest_port_set_name: + Name of field set for TCP destination ports. + When the `protocols` list contain both `tcp` and `udp`, + this key value + must be the same as `udp_dest_port_set_name`. + _custom_data: _custom_data + + """ + + class L4Applications(AvdIndexedList[str, L4ApplicationsItem]): + """Subclass of AvdIndexedList with `L4ApplicationsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + L4Applications._item_type = L4ApplicationsItem + + _fields: ClassVar[dict] = { + "ipv4_applications": {"type": Ipv4Applications}, + "l4_applications": {"type": L4Applications}, + "_custom_data": {"type": dict}, + } + ipv4_applications: Ipv4Applications + """ + List of user defined IPv4 applications. The name should be unique over all defined applications + (ipv4 and l4). + + Subclass of AvdIndexedList with `Ipv4ApplicationsItem` items. Primary key is `name` + (`str`). + """ + l4_applications: L4Applications + """ + List of user defined L4 applications. The name should be unique over all defined applications (ipv4 + and l4). + + Subclass of AvdIndexedList with `L4ApplicationsItem` items. Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4_applications: Ipv4Applications | UndefinedType = Undefined, + l4_applications: L4Applications | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Applications. + + + Subclass of AvdModel. + + Args: + ipv4_applications: + List of user defined IPv4 applications. The name should be unique over all defined applications + (ipv4 and l4). + + Subclass of AvdIndexedList with `Ipv4ApplicationsItem` items. Primary key is `name` + (`str`). + l4_applications: + List of user defined L4 applications. The name should be unique over all defined applications (ipv4 + and l4). + + Subclass of AvdIndexedList with `L4ApplicationsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class ApplicationProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class ApplicationsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "service": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + """Application Name.""" + service: Literal["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"] | None + """ + Service Name. + Specific service to target for this application. + If no service is specified, all + supported services of the application are matched. + Not all valid values are valid for all + applications, check on EOS CLI. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + service: Literal["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"] + | None + | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ApplicationsItem. + + + Subclass of AvdModel. + + Args: + name: Application Name. + service: + Service Name. + Specific service to target for this application. + If no service is specified, all + supported services of the application are matched. + Not all valid values are valid for all + applications, check on EOS CLI. + _custom_data: _custom_data + + """ + + class Applications(AvdList[ApplicationsItem]): + """Subclass of AvdList with `ApplicationsItem` items.""" + + Applications._item_type = ApplicationsItem + + class ApplicationTransports(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + ApplicationTransports._item_type = str + + class CategoriesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "service": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + """Name of a category.""" + service: Literal["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"] | None + """ + Service Name. + Specific service to target for this application. + If no service is specified, all + supported services of the application are matched. + Not all valid values are valid for all + applications, check on EOS CLI. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + service: Literal["audio-video", "chat", "default", "file-transfer", "networking-protocols", "peer-to-peer", "software-update"] + | None + | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CategoriesItem. + + + Subclass of AvdModel. + + Args: + name: Name of a category. + service: + Service Name. + Specific service to target for this application. + If no service is specified, all + supported services of the application are matched. + Not all valid values are valid for all + applications, check on EOS CLI. + _custom_data: _custom_data + + """ + + class Categories(AvdList[CategoriesItem]): + """Subclass of AvdList with `CategoriesItem` items.""" + + Categories._item_type = CategoriesItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "applications": {"type": Applications}, + "application_transports": {"type": ApplicationTransports}, + "categories": {"type": Categories}, + "_custom_data": {"type": dict}, + } + name: str + """Application Profile name.""" + applications: Applications + """ + List of applications part of the application profile. + + Subclass of AvdList with `ApplicationsItem` + items. + """ + application_transports: ApplicationTransports + """ + List of transport protocols. + + Subclass of AvdList with `str` items. + """ + categories: Categories + """ + Categories under this application profile. + + Subclass of AvdList with `CategoriesItem` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + applications: Applications | UndefinedType = Undefined, + application_transports: ApplicationTransports | UndefinedType = Undefined, + categories: Categories | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ApplicationProfilesItem. + + + Subclass of AvdModel. + + Args: + name: Application Profile name. + applications: + List of applications part of the application profile. + + Subclass of AvdList with `ApplicationsItem` + items. + application_transports: + List of transport protocols. + + Subclass of AvdList with `str` items. + categories: + Categories under this application profile. + + Subclass of AvdList with `CategoriesItem` items. + _custom_data: _custom_data + + """ + + class ApplicationProfiles(AvdIndexedList[str, ApplicationProfilesItem]): + """Subclass of AvdIndexedList with `ApplicationProfilesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + ApplicationProfiles._item_type = ApplicationProfilesItem + + _fields: ClassVar[dict] = { + "categories": {"type": Categories}, + "field_sets": {"type": FieldSets}, + "applications": {"type": Applications}, + "application_profiles": {"type": ApplicationProfiles}, + "_custom_data": {"type": dict}, + } + categories: Categories + """ + List of categories. + + Subclass of AvdIndexedList with `CategoriesItem` items. Primary key is `name` + (`str`). + """ + field_sets: FieldSets + """Subclass of AvdModel.""" + applications: Applications + """Subclass of AvdModel.""" + application_profiles: ApplicationProfiles + """ + Group of applications. + + Subclass of AvdIndexedList with `ApplicationProfilesItem` items. Primary key + is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + categories: Categories | UndefinedType = Undefined, + field_sets: FieldSets | UndefinedType = Undefined, + applications: Applications | UndefinedType = Undefined, + application_profiles: ApplicationProfiles | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ApplicationTrafficRecognition. + + + Subclass of AvdModel. + + Args: + categories: + List of categories. + + Subclass of AvdIndexedList with `CategoriesItem` items. Primary key is `name` + (`str`). + field_sets: Subclass of AvdModel. + applications: Subclass of AvdModel. + application_profiles: + Group of applications. + + Subclass of AvdIndexedList with `ApplicationProfilesItem` items. Primary key + is `name` (`str`). + _custom_data: _custom_data + + """ + + class Arp(AvdModel): + """Subclass of AvdModel.""" + + class Persistent(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "refresh_delay": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool + """Restore the ARP cache after reboot.""" + refresh_delay: int | None + """Time to wait in seconds before refreshing the ARP cache after reboot (EOS default 600).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + refresh_delay: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Persistent. + + + Subclass of AvdModel. + + Args: + enabled: Restore the ARP cache after reboot. + refresh_delay: Time to wait in seconds before refreshing the ARP cache after reboot (EOS default 600). + _custom_data: _custom_data + + """ + + class Aging(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"timeout_default": {"type": int}, "_custom_data": {"type": dict}} + timeout_default: int | None + """Timeout in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, timeout_default: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Aging. + + + Subclass of AvdModel. + + Args: + timeout_default: Timeout in seconds. + _custom_data: _custom_data + + """ + + class StaticEntriesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4_address": {"type": str}, "vrf": {"type": str}, "mac_address": {"type": str}, "_custom_data": {"type": dict}} + ipv4_address: str + """ARP entry IPv4 address.""" + vrf: str | None + """ARP entry VRF.""" + mac_address: str + """ARP entry MAC address.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4_address: str | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + mac_address: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StaticEntriesItem. + + + Subclass of AvdModel. + + Args: + ipv4_address: ARP entry IPv4 address. + vrf: ARP entry VRF. + mac_address: ARP entry MAC address. + _custom_data: _custom_data + + """ + + class StaticEntries(AvdList[StaticEntriesItem]): + """Subclass of AvdList with `StaticEntriesItem` items.""" + + StaticEntries._item_type = StaticEntriesItem + + _fields: ClassVar[dict] = { + "persistent": {"type": Persistent}, + "aging": {"type": Aging}, + "static_entries": {"type": StaticEntries}, + "_custom_data": {"type": dict}, + } + persistent: Persistent + """Subclass of AvdModel.""" + aging: Aging + """Subclass of AvdModel.""" + static_entries: StaticEntries + """ + Static ARP entries. + + Subclass of AvdList with `StaticEntriesItem` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + persistent: Persistent | UndefinedType = Undefined, + aging: Aging | UndefinedType = Undefined, + static_entries: StaticEntries | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Arp. + + + Subclass of AvdModel. + + Args: + persistent: Subclass of AvdModel. + aging: Subclass of AvdModel. + static_entries: + Static ARP entries. + + Subclass of AvdList with `StaticEntriesItem` items. + _custom_data: _custom_data + + """ + + class AsPath(AvdModel): + """Subclass of AvdModel.""" + + class AccessListsItem(AvdModel): + """Subclass of AvdModel.""" + + class EntriesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "type": {"type": str}, + "match": {"type": str}, + "origin": {"type": str, "default": "any"}, + "_custom_data": {"type": dict}, + } + type: Literal["permit", "deny"] | None + match: str | None + """Regex To Match.""" + origin: Literal["any", "egp", "igp", "incomplete"] + """Default value: `"any"`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + type: Literal["permit", "deny"] | None | UndefinedType = Undefined, + match: str | None | UndefinedType = Undefined, + origin: Literal["any", "egp", "igp", "incomplete"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EntriesItem. + + + Subclass of AvdModel. + + Args: + type: type + match: Regex To Match. + origin: origin + _custom_data: _custom_data + + """ + + class Entries(AvdList[EntriesItem]): + """Subclass of AvdList with `EntriesItem` items.""" + + Entries._item_type = EntriesItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "entries": {"type": Entries}, "_custom_data": {"type": dict}} + name: str + """Access List Name.""" + entries: Entries + """Subclass of AvdList with `EntriesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + entries: Entries | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AccessListsItem. + + + Subclass of AvdModel. + + Args: + name: Access List Name. + entries: Subclass of AvdList with `EntriesItem` items. + _custom_data: _custom_data + + """ + + class AccessLists(AvdIndexedList[str, AccessListsItem]): + """Subclass of AvdIndexedList with `AccessListsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + AccessLists._item_type = AccessListsItem + + _fields: ClassVar[dict] = {"regex_mode": {"type": str}, "access_lists": {"type": AccessLists}, "_custom_data": {"type": dict}} + regex_mode: Literal["asn", "string"] | None + access_lists: AccessLists + """Subclass of AvdIndexedList with `AccessListsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + regex_mode: Literal["asn", "string"] | None | UndefinedType = Undefined, + access_lists: AccessLists | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AsPath. + + + Subclass of AvdModel. + + Args: + regex_mode: regex_mode + access_lists: Subclass of AvdIndexedList with `AccessListsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class Banners(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"login": {"type": str}, "motd": {"type": str}, "_custom_data": {"type": dict}} + login: str | None + """Multiline string ending with EOF on the last line.""" + motd: str | None + """Multiline string ending with EOF on the last line.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + login: str | None | UndefinedType = Undefined, + motd: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Banners. + + + Subclass of AvdModel. + + Args: + login: Multiline string ending with EOF on the last line. + motd: Multiline string ending with EOF on the last line. + _custom_data: _custom_data + + """ + + class BgpGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class Neighbors(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Neighbors._item_type = str + + class BgpMaintenanceProfiles(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + BgpMaintenanceProfiles._item_type = str + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "vrf": {"type": str}, + "neighbors": {"type": Neighbors}, + "bgp_maintenance_profiles": {"type": BgpMaintenanceProfiles}, + "_custom_data": {"type": dict}, + } + name: str + """Group Name.""" + vrf: str | None + neighbors: Neighbors + """Subclass of AvdList with `str` items.""" + bgp_maintenance_profiles: BgpMaintenanceProfiles + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + bgp_maintenance_profiles: BgpMaintenanceProfiles | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BgpGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Group Name. + vrf: vrf + neighbors: Subclass of AvdList with `str` items. + bgp_maintenance_profiles: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class BgpGroups(AvdIndexedList[str, BgpGroupsItem]): + """Subclass of AvdIndexedList with `BgpGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + BgpGroups._item_type = BgpGroupsItem + + class Boot(AvdModel): + """Subclass of AvdModel.""" + + class Secret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"hash_algorithm": {"type": str, "default": "sha512"}, "key": {"type": str}, "_custom_data": {"type": dict}} + hash_algorithm: Literal["md5", "sha512"] + """Default value: `"sha512"`""" + key: str | None + """Hashed Password.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hash_algorithm: Literal["md5", "sha512"] | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Secret. + + + Subclass of AvdModel. + + Args: + hash_algorithm: hash_algorithm + key: Hashed Password. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"secret": {"type": Secret}, "_custom_data": {"type": dict}} + secret: Secret + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, secret: Secret | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Boot. + + + Subclass of AvdModel. + + Args: + secret: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class ClassMaps(AvdModel): + """Subclass of AvdModel.""" + + class PbrItem(AvdModel): + """Subclass of AvdModel.""" + + class Ip(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"access_group": {"type": str}, "_custom_data": {"type": dict}} + access_group: str | None + """Standard Access-List Name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, access_group: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Ip. + + + Subclass of AvdModel. + + Args: + access_group: Standard Access-List Name. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"name": {"type": str}, "ip": {"type": Ip}, "_custom_data": {"type": dict}} + name: str + """Class-Map Name.""" + ip: Ip + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, name: str | UndefinedType = Undefined, ip: Ip | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + PbrItem. + + + Subclass of AvdModel. + + Args: + name: Class-Map Name. + ip: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Pbr(AvdIndexedList[str, PbrItem]): + """Subclass of AvdIndexedList with `PbrItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Pbr._item_type = PbrItem + + class QosItem(AvdModel): + """Subclass of AvdModel.""" + + class Ip(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"access_group": {"type": str}, "_custom_data": {"type": dict}} + access_group: str | None + """IPv4 Access-List Name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, access_group: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Ip. + + + Subclass of AvdModel. + + Args: + access_group: IPv4 Access-List Name. + _custom_data: _custom_data + + """ + + class Ipv6(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"access_group": {"type": str}, "_custom_data": {"type": dict}} + access_group: str | None + """IPv6 Access-List Name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, access_group: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Ipv6. + + + Subclass of AvdModel. + + Args: + access_group: IPv6 Access-List Name. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "vlan": {"type": str}, + "cos": {"type": str}, + "ip": {"type": Ip}, + "ipv6": {"type": Ipv6}, + "_custom_data": {"type": dict}, + } + name: str + """Class-Map Name.""" + vlan: str | None + """VLAN value(s) or range(s) of VLAN values.""" + cos: str | None + """CoS value(s) or range(s) of CoS values.""" + ip: Ip + """Subclass of AvdModel.""" + ipv6: Ipv6 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + vlan: str | None | UndefinedType = Undefined, + cos: str | None | UndefinedType = Undefined, + ip: Ip | UndefinedType = Undefined, + ipv6: Ipv6 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + QosItem. + + + Subclass of AvdModel. + + Args: + name: Class-Map Name. + vlan: VLAN value(s) or range(s) of VLAN values. + cos: CoS value(s) or range(s) of CoS values. + ip: Subclass of AvdModel. + ipv6: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Qos(AvdIndexedList[str, QosItem]): + """Subclass of AvdIndexedList with `QosItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Qos._item_type = QosItem + + _fields: ClassVar[dict] = {"pbr": {"type": Pbr}, "qos": {"type": Qos}, "_custom_data": {"type": dict}} + pbr: Pbr + """Subclass of AvdIndexedList with `PbrItem` items. Primary key is `name` (`str`).""" + qos: Qos + """Subclass of AvdIndexedList with `QosItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, pbr: Pbr | UndefinedType = Undefined, qos: Qos | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + ClassMaps. + + + Subclass of AvdModel. + + Args: + pbr: Subclass of AvdIndexedList with `PbrItem` items. Primary key is `name` (`str`). + qos: Subclass of AvdIndexedList with `QosItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class Clock(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"timezone": {"type": str}, "_custom_data": {"type": dict}} + timezone: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, timezone: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Clock. + + + Subclass of AvdModel. + + Args: + timezone: timezone + _custom_data: _custom_data + + """ + + class CommunityListsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "action": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Community-list Name.""" + action: str + """ + Action as string. + Example: "permit GSHUT 65123:123" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + action: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CommunityListsItem. + + + Subclass of AvdModel. + + Args: + name: Community-list Name. + action: + Action as string. + Example: "permit GSHUT 65123:123" + _custom_data: _custom_data + + """ + + class CommunityLists(AvdIndexedList[str, CommunityListsItem]): + """Subclass of AvdIndexedList with `CommunityListsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + CommunityLists._item_type = CommunityListsItem + + class CustomTemplates(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + CustomTemplates._item_type = str + + class Cvx(AvdModel): + """Subclass of AvdModel.""" + + class PeerHosts(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + PeerHosts._item_type = str + + class Services(AvdModel): + """Subclass of AvdModel.""" + + class Mcs(AvdModel): + """Subclass of AvdModel.""" + + class Redis(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"password": {"type": str}, "password_type": {"type": str, "default": "7"}, "_custom_data": {"type": dict}} + password: str | None + """Hashed password using the password_type.""" + password_type: Literal["0", "7", "8a"] + """Default value: `"7"`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + password: str | None | UndefinedType = Undefined, + password_type: Literal["0", "7", "8a"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Redis. + + + Subclass of AvdModel. + + Args: + password: Hashed password using the password_type. + password_type: password_type + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"redis": {"type": Redis}, "shutdown": {"type": bool}, "_custom_data": {"type": dict}} + redis: Redis + """Subclass of AvdModel.""" + shutdown: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + redis: Redis | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Mcs. + + + Subclass of AvdModel. + + Args: + redis: Subclass of AvdModel. + shutdown: shutdown + _custom_data: _custom_data + + """ + + class Vxlan(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"shutdown": {"type": bool}, "vtep_mac_learning": {"type": str}, "_custom_data": {"type": dict}} + shutdown: bool | None + vtep_mac_learning: Literal["control-plane", "data-plane"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + shutdown: bool | None | UndefinedType = Undefined, + vtep_mac_learning: Literal["control-plane", "data-plane"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Vxlan. + + + Subclass of AvdModel. + + Args: + shutdown: shutdown + vtep_mac_learning: vtep_mac_learning + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"mcs": {"type": Mcs}, "vxlan": {"type": Vxlan}, "_custom_data": {"type": dict}} + mcs: Mcs + """Subclass of AvdModel.""" + vxlan: Vxlan + """ + VXLAN Controller service. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mcs: Mcs | UndefinedType = Undefined, + vxlan: Vxlan | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Services. + + + Subclass of AvdModel. + + Args: + mcs: Subclass of AvdModel. + vxlan: + VXLAN Controller service. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "shutdown": {"type": bool}, + "peer_hosts": {"type": PeerHosts}, + "services": {"type": Services}, + "_custom_data": {"type": dict}, + } + shutdown: bool | None + peer_hosts: PeerHosts + """Subclass of AvdList with `str` items.""" + services: Services + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + shutdown: bool | None | UndefinedType = Undefined, + peer_hosts: PeerHosts | UndefinedType = Undefined, + services: Services | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Cvx. + + + Subclass of AvdModel. + + Args: + shutdown: shutdown + peer_hosts: Subclass of AvdList with `str` items. + services: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class DaemonTerminattr(AvdModel): + """Subclass of AvdModel.""" + + class Cvaddrs(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Cvaddrs._item_type = str + + class ClustersItem(AvdModel): + """Subclass of AvdModel.""" + + class Cvaddrs(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Cvaddrs._item_type = str + + class Cvauth(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "method": {"type": str}, + "key": {"type": str}, + "token_file": {"type": str}, + "cert_file": {"type": str}, + "ca_file": {"type": str}, + "key_file": {"type": str}, + "_custom_data": {"type": dict}, + } + method: Literal["token", "token-secure", "key", "certs"] | None + key: str | None + token_file: str | None + """ + Token file path. + e.g. "/tmp/token" + """ + cert_file: str | None + """ + Client certificate file path. + e.g. "/persist/secure/ssl/terminattr/primary/certs/client.crt" + """ + ca_file: str | None + """ + CA certificate file path (on-prem only). + e.g. "/persist/secure/ssl/terminattr/primary/certs/ca.crt" + """ + key_file: str | None + """ + Client certificate key file path. + e.g. "/persist/secure/ssl/terminattr/primary/keys/client.key" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + method: Literal["token", "token-secure", "key", "certs"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + token_file: str | None | UndefinedType = Undefined, + cert_file: str | None | UndefinedType = Undefined, + ca_file: str | None | UndefinedType = Undefined, + key_file: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Cvauth. + + + Subclass of AvdModel. + + Args: + method: method + key: key + token_file: + Token file path. + e.g. "/tmp/token" + cert_file: + Client certificate file path. + e.g. "/persist/secure/ssl/terminattr/primary/certs/client.crt" + ca_file: + CA certificate file path (on-prem only). + e.g. "/persist/secure/ssl/terminattr/primary/certs/ca.crt" + key_file: + Client certificate key file path. + e.g. "/persist/secure/ssl/terminattr/primary/keys/client.key" + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "cvaddrs": {"type": Cvaddrs}, + "cvauth": {"type": Cvauth}, + "cvobscurekeyfile": {"type": bool}, + "cvproxy": {"type": str}, + "cvsourceip": {"type": str}, + "cvsourceintf": {"type": str}, + "cvvrf": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Cluster Name.""" + cvaddrs: Cvaddrs + """ + Streaming address(es) for CloudVision cluster. + - TCP 9910 is used for CV on-prem + - TCP 443 is used + for CV as a Service + + + Subclass of AvdList with `str` items. + """ + cvauth: Cvauth + """ + Authentication scheme used to connect to CloudVision. + + + Subclass of AvdModel. + """ + cvobscurekeyfile: bool | None + """Encrypt the private key used for authentication to CloudVision.""" + cvproxy: str | None + """ + Proxy server through which CloudVision is reachable. Useful when the CloudVision server is hosted in + the cloud. + The expected form is http://[user:password@]ip:port, e.g.: + `http://arista:arista@10.83.12.78:3128`. Available as of TerminAttr v1.13.0. + """ + cvsourceip: str | None + """Set source IP address in case of in-band management.""" + cvsourceintf: str | None + """ + Set source interface in case of in-band management. Available as of TerminAttr v1.23.0. + The + interface name is case sensitive and has to match the interface name in the running-config, + e.g.:Vlan100. + """ + cvvrf: str | None + """The VRF to use to connect to CloudVision.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + cvaddrs: Cvaddrs | UndefinedType = Undefined, + cvauth: Cvauth | UndefinedType = Undefined, + cvobscurekeyfile: bool | None | UndefinedType = Undefined, + cvproxy: str | None | UndefinedType = Undefined, + cvsourceip: str | None | UndefinedType = Undefined, + cvsourceintf: str | None | UndefinedType = Undefined, + cvvrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ClustersItem. + + + Subclass of AvdModel. + + Args: + name: Cluster Name. + cvaddrs: + Streaming address(es) for CloudVision cluster. + - TCP 9910 is used for CV on-prem + - TCP 443 is used + for CV as a Service + + + Subclass of AvdList with `str` items. + cvauth: + Authentication scheme used to connect to CloudVision. + + + Subclass of AvdModel. + cvobscurekeyfile: Encrypt the private key used for authentication to CloudVision. + cvproxy: + Proxy server through which CloudVision is reachable. Useful when the CloudVision server is hosted in + the cloud. + The expected form is http://[user:password@]ip:port, e.g.: + `http://arista:arista@10.83.12.78:3128`. Available as of TerminAttr v1.13.0. + cvsourceip: Set source IP address in case of in-band management. + cvsourceintf: + Set source interface in case of in-band management. Available as of TerminAttr v1.23.0. + The + interface name is case sensitive and has to match the interface name in the running-config, + e.g.:Vlan100. + cvvrf: The VRF to use to connect to CloudVision. + _custom_data: _custom_data + + """ + + class Clusters(AvdIndexedList[str, ClustersItem]): + """Subclass of AvdIndexedList with `ClustersItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Clusters._item_type = ClustersItem + + class Cvauth(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "method": {"type": str}, + "key": {"type": str}, + "token_file": {"type": str}, + "cert_file": {"type": str}, + "ca_file": {"type": str}, + "key_file": {"type": str}, + "_custom_data": {"type": dict}, + } + method: Literal["token", "token-secure", "key", "certs"] | None + key: str | None + token_file: str | None + """ + Token file path. + e.g. "/tmp/token" + """ + cert_file: str | None + """ + Client certificate file path. + e.g. "/persist/secure/ssl/terminattr/primary/certs/client.crt" + """ + ca_file: str | None + """ + CA certificate file path (on-prem only). + e.g. "/persist/secure/ssl/terminattr/primary/certs/ca.crt" + """ + key_file: str | None + """ + Client certificate key file path. + e.g. "/persist/secure/ssl/terminattr/primary/keys/client.key" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + method: Literal["token", "token-secure", "key", "certs"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + token_file: str | None | UndefinedType = Undefined, + cert_file: str | None | UndefinedType = Undefined, + ca_file: str | None | UndefinedType = Undefined, + key_file: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Cvauth. + + + Subclass of AvdModel. + + Args: + method: method + key: key + token_file: + Token file path. + e.g. "/tmp/token" + cert_file: + Client certificate file path. + e.g. "/persist/secure/ssl/terminattr/primary/certs/client.crt" + ca_file: + CA certificate file path (on-prem only). + e.g. "/persist/secure/ssl/terminattr/primary/certs/ca.crt" + key_file: + Client certificate key file path. + e.g. "/persist/secure/ssl/terminattr/primary/keys/client.key" + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "cvaddrs": {"type": Cvaddrs}, + "clusters": {"type": Clusters}, + "cvauth": {"type": Cvauth}, + "cvobscurekeyfile": {"type": bool}, + "cvproxy": {"type": str}, + "cvsourceip": {"type": str}, + "cvsourceintf": {"type": str}, + "cvvrf": {"type": str}, + "cvgnmi": {"type": bool}, + "disable_aaa": {"type": bool}, + "grpcaddr": {"type": str}, + "grpcreadonly": {"type": bool}, + "ingestexclude": {"type": str}, + "smashexcludes": {"type": str}, + "taillogs": {"type": str}, + "ecodhcpaddr": {"type": str}, + "ipfix": {"type": bool}, + "ipfixaddr": {"type": str}, + "sflow": {"type": bool}, + "sflowaddr": {"type": str}, + "cvconfig": {"type": bool}, + "_custom_data": {"type": dict}, + } + cvaddrs: Cvaddrs + """ + Streaming address(es) for CloudVision single cluster. + - TCP 9910 is used for CV on-prem + - TCP 443 is + used for CV as a Service + + + Subclass of AvdList with `str` items. + """ + clusters: Clusters + """ + Multiple CloudVision clusters. + + + Subclass of AvdIndexedList with `ClustersItem` items. Primary key + is `name` (`str`). + """ + cvauth: Cvauth + """ + Authentication scheme used to connect to CloudVision. + + + Subclass of AvdModel. + """ + cvobscurekeyfile: bool | None + """Encrypt the private key used for authentication to CloudVision.""" + cvproxy: str | None + """ + Proxy server through which CloudVision is reachable. Useful when the CloudVision server is hosted in + the cloud. + The expected form is http://[user:password@]ip:port, e.g.: + `http://arista:arista@10.83.12.78:3128`. Available as of TerminAttr v1.13.0. + """ + cvsourceip: str | None + """Set source IP address in case of in-band management.""" + cvsourceintf: str | None + """ + Set source interface in case of in-band management. + The interface name is case sensitive and has to + match the interface name in the running-config, e.g.:Vlan100. + """ + cvvrf: str | None + """The VRF to use to connect to CloudVision.""" + cvgnmi: bool | None + """Stream states from EOS gNMI servers (Openconfig) to CloudVision. Available as of TerminAttr v1.13.1.""" + disable_aaa: bool | None + """ + Disable AAA authorization and accounting. + When setting this flag, all commands pushed from + CloudVision are applied directly to the CLI without authorization. + """ + grpcaddr: str | None + """ + Set the gRPC server address, the default is 127.0.0.1:6042. + e.g. "MGMT/0.0.0.0:6042" + """ + grpcreadonly: bool | None + """gNMI read-only mode - Disable gnmi.Set().""" + ingestexclude: str | None + """ + Exclude paths from Sysdb on the ingest side. + e.g. "/Sysdb/cell/1/agent,/Sysdb/cell/2/agent" + """ + smashexcludes: str | None + """ + Exclude paths from the shared memory table. + e.g. "ale,flexCounter,hardware,kni,pulse,strata" + """ + taillogs: str | None + """ + Enable log file collection; /var/log/messages is streamed by default if no path is set. + e.g. + "/var/log/messages" + """ + ecodhcpaddr: str | None + """ + ECO DHCP Collector address or ECO DHCP Fingerprint listening address in standalone mode (default + "127.0.0.1:67"). + """ + ipfix: bool | None + """ + Enable IPFIX provider (TerminAttr default is true). + This flag is enabled by default and does not + have to be added to the daemon configuration. + """ + ipfixaddr: str | None + """ + ECO IPFIX Collector address to listen on to receive IPFIX packets (TerminAttr default + "127.0.0.1:4739"). + """ + sflow: bool | None + """Enable sFlow provider (TerminAttr default is true).""" + sflowaddr: str | None + """ + ECO sFlow Collector address to listen on to receive sFlow packets (TerminAttr default + "127.0.0.1:6343"). + """ + cvconfig: bool | None + """Subscribe to dynamic device configuration from CloudVision (TerminAttr default is false).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + cvaddrs: Cvaddrs | UndefinedType = Undefined, + clusters: Clusters | UndefinedType = Undefined, + cvauth: Cvauth | UndefinedType = Undefined, + cvobscurekeyfile: bool | None | UndefinedType = Undefined, + cvproxy: str | None | UndefinedType = Undefined, + cvsourceip: str | None | UndefinedType = Undefined, + cvsourceintf: str | None | UndefinedType = Undefined, + cvvrf: str | None | UndefinedType = Undefined, + cvgnmi: bool | None | UndefinedType = Undefined, + disable_aaa: bool | None | UndefinedType = Undefined, + grpcaddr: str | None | UndefinedType = Undefined, + grpcreadonly: bool | None | UndefinedType = Undefined, + ingestexclude: str | None | UndefinedType = Undefined, + smashexcludes: str | None | UndefinedType = Undefined, + taillogs: str | None | UndefinedType = Undefined, + ecodhcpaddr: str | None | UndefinedType = Undefined, + ipfix: bool | None | UndefinedType = Undefined, + ipfixaddr: str | None | UndefinedType = Undefined, + sflow: bool | None | UndefinedType = Undefined, + sflowaddr: str | None | UndefinedType = Undefined, + cvconfig: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DaemonTerminattr. + + + Subclass of AvdModel. + + Args: + cvaddrs: + Streaming address(es) for CloudVision single cluster. + - TCP 9910 is used for CV on-prem + - TCP 443 is + used for CV as a Service + + + Subclass of AvdList with `str` items. + clusters: + Multiple CloudVision clusters. + + + Subclass of AvdIndexedList with `ClustersItem` items. Primary key + is `name` (`str`). + cvauth: + Authentication scheme used to connect to CloudVision. + + + Subclass of AvdModel. + cvobscurekeyfile: Encrypt the private key used for authentication to CloudVision. + cvproxy: + Proxy server through which CloudVision is reachable. Useful when the CloudVision server is hosted in + the cloud. + The expected form is http://[user:password@]ip:port, e.g.: + `http://arista:arista@10.83.12.78:3128`. Available as of TerminAttr v1.13.0. + cvsourceip: Set source IP address in case of in-band management. + cvsourceintf: + Set source interface in case of in-band management. + The interface name is case sensitive and has to + match the interface name in the running-config, e.g.:Vlan100. + cvvrf: The VRF to use to connect to CloudVision. + cvgnmi: Stream states from EOS gNMI servers (Openconfig) to CloudVision. Available as of TerminAttr v1.13.1. + disable_aaa: + Disable AAA authorization and accounting. + When setting this flag, all commands pushed from + CloudVision are applied directly to the CLI without authorization. + grpcaddr: + Set the gRPC server address, the default is 127.0.0.1:6042. + e.g. "MGMT/0.0.0.0:6042" + grpcreadonly: gNMI read-only mode - Disable gnmi.Set(). + ingestexclude: + Exclude paths from Sysdb on the ingest side. + e.g. "/Sysdb/cell/1/agent,/Sysdb/cell/2/agent" + smashexcludes: + Exclude paths from the shared memory table. + e.g. "ale,flexCounter,hardware,kni,pulse,strata" + taillogs: + Enable log file collection; /var/log/messages is streamed by default if no path is set. + e.g. + "/var/log/messages" + ecodhcpaddr: + ECO DHCP Collector address or ECO DHCP Fingerprint listening address in standalone mode (default + "127.0.0.1:67"). + ipfix: + Enable IPFIX provider (TerminAttr default is true). + This flag is enabled by default and does not + have to be added to the daemon configuration. + ipfixaddr: + ECO IPFIX Collector address to listen on to receive IPFIX packets (TerminAttr default + "127.0.0.1:4739"). + sflow: Enable sFlow provider (TerminAttr default is true). + sflowaddr: + ECO sFlow Collector address to listen on to receive sFlow packets (TerminAttr default + "127.0.0.1:6343"). + cvconfig: Subscribe to dynamic device configuration from CloudVision (TerminAttr default is false). + _custom_data: _custom_data + + """ + + class DaemonsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "exec": {"type": str}, "enabled": {"type": bool, "default": True}, "_custom_data": {"type": dict}} + name: str + """Daemon Name.""" + exec: str + """command to run as a daemon.""" + enabled: bool + """Default value: `True`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + exec: str | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DaemonsItem. + + + Subclass of AvdModel. + + Args: + name: Daemon Name. + exec: command to run as a daemon. + enabled: enabled + _custom_data: _custom_data + + """ + + class Daemons(AvdIndexedList[str, DaemonsItem]): + """Subclass of AvdIndexedList with `DaemonsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Daemons._item_type = DaemonsItem + + class DhcpRelay(AvdModel): + """Subclass of AvdModel.""" + + class Servers(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Servers._item_type = str + + _fields: ClassVar[dict] = { + "servers": {"type": Servers}, + "tunnel_requests_disabled": {"type": bool}, + "mlag_peerlink_requests_disabled": {"type": bool}, + "_custom_data": {"type": dict}, + } + servers: Servers + """Subclass of AvdList with `str` items.""" + tunnel_requests_disabled: bool | None + mlag_peerlink_requests_disabled: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + servers: Servers | UndefinedType = Undefined, + tunnel_requests_disabled: bool | None | UndefinedType = Undefined, + mlag_peerlink_requests_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DhcpRelay. + + + Subclass of AvdModel. + + Args: + servers: Subclass of AvdList with `str` items. + tunnel_requests_disabled: tunnel_requests_disabled + mlag_peerlink_requests_disabled: mlag_peerlink_requests_disabled + _custom_data: _custom_data + + """ + + class DhcpServersItem(AvdModel): + """Subclass of AvdModel.""" + + class LeaseTimeIpv4(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"days": {"type": int}, "hours": {"type": int}, "minutes": {"type": int}, "_custom_data": {"type": dict}} + days: int + hours: int + minutes: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + days: int | UndefinedType = Undefined, + hours: int | UndefinedType = Undefined, + minutes: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LeaseTimeIpv4. + + + Subclass of AvdModel. + + Args: + days: days + hours: hours + minutes: minutes + _custom_data: _custom_data + + """ + + class LeaseTimeIpv6(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"days": {"type": int}, "hours": {"type": int}, "minutes": {"type": int}, "_custom_data": {"type": dict}} + days: int + hours: int + minutes: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + days: int | UndefinedType = Undefined, + hours: int | UndefinedType = Undefined, + minutes: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LeaseTimeIpv6. + + + Subclass of AvdModel. + + Args: + days: days + hours: hours + minutes: minutes + _custom_data: _custom_data + + """ + + class DnsServersIpv4(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DnsServersIpv4._item_type = str + + class DnsServersIpv6(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DnsServersIpv6._item_type = str + + class TftpServer(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"file_ipv4": {"type": str}, "file_ipv6": {"type": str}, "_custom_data": {"type": dict}} + file_ipv4: str | None + """Name of TFTP file for IPv4 clients.""" + file_ipv6: str | None + """Name of TFTP file for IPv6 clients.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + file_ipv4: str | None | UndefinedType = Undefined, + file_ipv6: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TftpServer. + + + Subclass of AvdModel. + + Args: + file_ipv4: Name of TFTP file for IPv4 clients. + file_ipv6: Name of TFTP file for IPv6 clients. + _custom_data: _custom_data + + """ + + class Ipv4VendorOptionsItem(AvdModel): + """Subclass of AvdModel.""" + + class SubOptionsItem(AvdModel): + """Subclass of AvdModel.""" + + class ArrayIpv4Address(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + ArrayIpv4Address._item_type = str + + _fields: ClassVar[dict] = { + "code": {"type": int}, + "string": {"type": str}, + "ipv4_address": {"type": str}, + "array_ipv4_address": {"type": ArrayIpv4Address}, + "_custom_data": {"type": dict}, + } + code: int + string: str | None + """ + String value for suboption data. + Only one of `string`, `ipv4_address` and `array_ipv4_address` + variables should be used for any one suboption. + The order of precedence if multiple of these + variables are defined is `string` -> `ipv4_address` -> `array_ipv4_address`. + """ + ipv4_address: str | None + """ + IPv4 address value for suboption data. + Only one of `string`, `ipv4_address` and `array_ipv4_address` + variables should be used for any one suboption. + The order of precedence if multiple of these + variables are defined is `string` -> `ipv4_address` -> `array_ipv4_address`. + """ + array_ipv4_address: ArrayIpv4Address + """ + Array of IPv4 addresses for suboption data. + Only one of `string`, `ipv4_address` and + `array_ipv4_address` variables should be used for any one suboption. + The order of precedence if + multiple of these variables are defined is `string` -> `ipv4_address` -> `array_ipv4_address`. + Subclass of AvdList with `str` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + code: int | UndefinedType = Undefined, + string: str | None | UndefinedType = Undefined, + ipv4_address: str | None | UndefinedType = Undefined, + array_ipv4_address: ArrayIpv4Address | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SubOptionsItem. + + + Subclass of AvdModel. + + Args: + code: code + string: + String value for suboption data. + Only one of `string`, `ipv4_address` and `array_ipv4_address` + variables should be used for any one suboption. + The order of precedence if multiple of these + variables are defined is `string` -> `ipv4_address` -> `array_ipv4_address`. + ipv4_address: + IPv4 address value for suboption data. + Only one of `string`, `ipv4_address` and `array_ipv4_address` + variables should be used for any one suboption. + The order of precedence if multiple of these + variables are defined is `string` -> `ipv4_address` -> `array_ipv4_address`. + array_ipv4_address: + Array of IPv4 addresses for suboption data. + Only one of `string`, `ipv4_address` and + `array_ipv4_address` variables should be used for any one suboption. + The order of precedence if + multiple of these variables are defined is `string` -> `ipv4_address` -> `array_ipv4_address`. + Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class SubOptions(AvdIndexedList[int, SubOptionsItem]): + """Subclass of AvdIndexedList with `SubOptionsItem` items. Primary key is `code` (`int`).""" + + _primary_key: ClassVar[str] = "code" + + SubOptions._item_type = SubOptionsItem + + _fields: ClassVar[dict] = {"vendor_id": {"type": str}, "sub_options": {"type": SubOptions}, "_custom_data": {"type": dict}} + vendor_id: str + sub_options: SubOptions + """Subclass of AvdIndexedList with `SubOptionsItem` items. Primary key is `code` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + vendor_id: str | UndefinedType = Undefined, + sub_options: SubOptions | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4VendorOptionsItem. + + + Subclass of AvdModel. + + Args: + vendor_id: vendor_id + sub_options: Subclass of AvdIndexedList with `SubOptionsItem` items. Primary key is `code` (`int`). + _custom_data: _custom_data + + """ + + class Ipv4VendorOptions(AvdIndexedList[str, Ipv4VendorOptionsItem]): + """Subclass of AvdIndexedList with `Ipv4VendorOptionsItem` items. Primary key is `vendor_id` (`str`).""" + + _primary_key: ClassVar[str] = "vendor_id" + + Ipv4VendorOptions._item_type = Ipv4VendorOptionsItem + + class SubnetsItem(AvdModel): + """Subclass of AvdModel.""" + + class DnsServers(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DnsServers._item_type = str + + class RangesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"start": {"type": str}, "end": {"type": str}, "_custom_data": {"type": dict}} + start: str + end: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + start: str | UndefinedType = Undefined, + end: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RangesItem. + + + Subclass of AvdModel. + + Args: + start: start + end: end + _custom_data: _custom_data + + """ + + class Ranges(AvdList[RangesItem]): + """Subclass of AvdList with `RangesItem` items.""" + + Ranges._item_type = RangesItem + + class LeaseTime(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"days": {"type": int}, "hours": {"type": int}, "minutes": {"type": int}, "_custom_data": {"type": dict}} + days: int + hours: int + minutes: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + days: int | UndefinedType = Undefined, + hours: int | UndefinedType = Undefined, + minutes: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LeaseTime. + + + Subclass of AvdModel. + + Args: + days: days + hours: hours + minutes: minutes + _custom_data: _custom_data + + """ + + class ReservationsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "mac_address": {"type": str}, + "hostname": {"type": str}, + "ipv4_address": {"type": str}, + "ipv6_address": {"type": str}, + "_custom_data": {"type": dict}, + } + mac_address: str + """Ethernet address in format - HHHH.HHHH.HHHH""" + hostname: str | None + ipv4_address: str | None + """ + Valid IPv4 address from the given subnet. + This should only be used within an IPv4 subnet. + """ + ipv6_address: str | None + """ + Valid IPv6 address from the given subnet. + This should only be used within an IPv6 subnet. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mac_address: str | UndefinedType = Undefined, + hostname: str | None | UndefinedType = Undefined, + ipv4_address: str | None | UndefinedType = Undefined, + ipv6_address: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ReservationsItem. + + + Subclass of AvdModel. + + Args: + mac_address: Ethernet address in format - HHHH.HHHH.HHHH + hostname: hostname + ipv4_address: + Valid IPv4 address from the given subnet. + This should only be used within an IPv4 subnet. + ipv6_address: + Valid IPv6 address from the given subnet. + This should only be used within an IPv6 subnet. + _custom_data: _custom_data + + """ + + class Reservations(AvdIndexedList[str, ReservationsItem]): + """Subclass of AvdIndexedList with `ReservationsItem` items. Primary key is `mac_address` (`str`).""" + + _primary_key: ClassVar[str] = "mac_address" + + Reservations._item_type = ReservationsItem + + _fields: ClassVar[dict] = { + "subnet": {"type": str}, + "name": {"type": str}, + "default_gateway": {"type": str}, + "dns_servers": {"type": DnsServers}, + "ranges": {"type": Ranges}, + "lease_time": {"type": LeaseTime}, + "reservations": {"type": Reservations}, + "_custom_data": {"type": dict}, + } + subnet: str + """IPv4/IPv6 subnet.""" + name: str | None + default_gateway: str | None + dns_servers: DnsServers + """Subclass of AvdList with `str` items.""" + ranges: Ranges + """Subclass of AvdList with `RangesItem` items.""" + lease_time: LeaseTime + """Subclass of AvdModel.""" + reservations: Reservations + """ + DHCP client reservations. + + Subclass of AvdIndexedList with `ReservationsItem` items. Primary key is + `mac_address` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + subnet: str | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + default_gateway: str | None | UndefinedType = Undefined, + dns_servers: DnsServers | UndefinedType = Undefined, + ranges: Ranges | UndefinedType = Undefined, + lease_time: LeaseTime | UndefinedType = Undefined, + reservations: Reservations | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SubnetsItem. + + + Subclass of AvdModel. + + Args: + subnet: IPv4/IPv6 subnet. + name: name + default_gateway: default_gateway + dns_servers: Subclass of AvdList with `str` items. + ranges: Subclass of AvdList with `RangesItem` items. + lease_time: Subclass of AvdModel. + reservations: + DHCP client reservations. + + Subclass of AvdIndexedList with `ReservationsItem` items. Primary key is + `mac_address` (`str`). + _custom_data: _custom_data + + """ + + class Subnets(AvdIndexedList[str, SubnetsItem]): + """Subclass of AvdIndexedList with `SubnetsItem` items. Primary key is `subnet` (`str`).""" + + _primary_key: ClassVar[str] = "subnet" + + Subnets._item_type = SubnetsItem + + _fields: ClassVar[dict] = { + "disabled": {"type": bool}, + "vrf": {"type": str}, + "lease_time_ipv4": {"type": LeaseTimeIpv4}, + "lease_time_ipv6": {"type": LeaseTimeIpv6}, + "dns_domain_name_ipv4": {"type": str}, + "dns_domain_name_ipv6": {"type": str}, + "dns_servers_ipv4": {"type": DnsServersIpv4}, + "dns_servers_ipv6": {"type": DnsServersIpv6}, + "tftp_server": {"type": TftpServer}, + "ipv4_vendor_options": {"type": Ipv4VendorOptions}, + "subnets": {"type": Subnets}, + "eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + disabled: bool | None + vrf: str + """VRF in which to configure the DHCP server, use `default` to indicate default VRF.""" + lease_time_ipv4: LeaseTimeIpv4 + """Subclass of AvdModel.""" + lease_time_ipv6: LeaseTimeIpv6 + """Subclass of AvdModel.""" + dns_domain_name_ipv4: str | None + dns_domain_name_ipv6: str | None + dns_servers_ipv4: DnsServersIpv4 + """ + List of DNS servers for IPv4 clients. + + Subclass of AvdList with `str` items. + """ + dns_servers_ipv6: DnsServersIpv6 + """ + List of DNS servers for IPv6 clients. + + Subclass of AvdList with `str` items. + """ + tftp_server: TftpServer + """Subclass of AvdModel.""" + ipv4_vendor_options: Ipv4VendorOptions + """Subclass of AvdIndexedList with `Ipv4VendorOptionsItem` items. Primary key is `vendor_id` (`str`).""" + subnets: Subnets + """Subclass of AvdIndexedList with `SubnetsItem` items. Primary key is `subnet` (`str`).""" + eos_cli: str | None + """Multiline EOS CLI rendered directly on the dhcp server in the final EOS configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + disabled: bool | None | UndefinedType = Undefined, + vrf: str | UndefinedType = Undefined, + lease_time_ipv4: LeaseTimeIpv4 | UndefinedType = Undefined, + lease_time_ipv6: LeaseTimeIpv6 | UndefinedType = Undefined, + dns_domain_name_ipv4: str | None | UndefinedType = Undefined, + dns_domain_name_ipv6: str | None | UndefinedType = Undefined, + dns_servers_ipv4: DnsServersIpv4 | UndefinedType = Undefined, + dns_servers_ipv6: DnsServersIpv6 | UndefinedType = Undefined, + tftp_server: TftpServer | UndefinedType = Undefined, + ipv4_vendor_options: Ipv4VendorOptions | UndefinedType = Undefined, + subnets: Subnets | UndefinedType = Undefined, + eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DhcpServersItem. + + + Subclass of AvdModel. + + Args: + disabled: disabled + vrf: VRF in which to configure the DHCP server, use `default` to indicate default VRF. + lease_time_ipv4: Subclass of AvdModel. + lease_time_ipv6: Subclass of AvdModel. + dns_domain_name_ipv4: dns_domain_name_ipv4 + dns_domain_name_ipv6: dns_domain_name_ipv6 + dns_servers_ipv4: + List of DNS servers for IPv4 clients. + + Subclass of AvdList with `str` items. + dns_servers_ipv6: + List of DNS servers for IPv6 clients. + + Subclass of AvdList with `str` items. + tftp_server: Subclass of AvdModel. + ipv4_vendor_options: Subclass of AvdIndexedList with `Ipv4VendorOptionsItem` items. Primary key is `vendor_id` (`str`). + subnets: Subclass of AvdIndexedList with `SubnetsItem` items. Primary key is `subnet` (`str`). + eos_cli: Multiline EOS CLI rendered directly on the dhcp server in the final EOS configuration. + _custom_data: _custom_data + + """ + + class DhcpServers(AvdIndexedList[str, DhcpServersItem]): + """Subclass of AvdIndexedList with `DhcpServersItem` items. Primary key is `vrf` (`str`).""" + + _primary_key: ClassVar[str] = "vrf" + + DhcpServers._item_type = DhcpServersItem + + class DomainList(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DomainList._item_type = str + + class Dot1x(AvdModel): + """Subclass of AvdModel.""" + + class MacBasedAuthentication(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"delay": {"type": int}, "hold_period": {"type": int}, "_custom_data": {"type": dict}} + delay: int | None + hold_period: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + delay: int | None | UndefinedType = Undefined, + hold_period: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MacBasedAuthentication. + + + Subclass of AvdModel. + + Args: + delay: delay + hold_period: hold_period + _custom_data: _custom_data + + """ + + class RadiusAvPairUsernameFormat(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"delimiter": {"type": str}, "mac_string_case": {"type": str}, "_custom_data": {"type": dict}} + delimiter: Literal["colon", "hyphen", "none", "period"] + """Delimiter to use in MAC address string.""" + mac_string_case: Literal["lowercase", "uppercase"] + """MAC address string in lowercase/uppercase.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + delimiter: Literal["colon", "hyphen", "none", "period"] | UndefinedType = Undefined, + mac_string_case: Literal["lowercase", "uppercase"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RadiusAvPairUsernameFormat. + + + Subclass of AvdModel. + + Args: + delimiter: Delimiter to use in MAC address string. + mac_string_case: MAC address string in lowercase/uppercase. + _custom_data: _custom_data + + """ + + class RadiusAvPair(AvdModel): + """Subclass of AvdModel.""" + + class Lldp(AvdModel): + """Subclass of AvdModel.""" + + class SystemName(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "auth_only": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool + auth_only: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + auth_only: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SystemName. + + + Subclass of AvdModel. + + Args: + enabled: enabled + auth_only: auth_only + _custom_data: _custom_data + + """ + + class SystemDescription(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "auth_only": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool + auth_only: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + auth_only: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SystemDescription. + + + Subclass of AvdModel. + + Args: + enabled: enabled + auth_only: auth_only + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "system_name": {"type": SystemName}, + "system_description": {"type": SystemDescription}, + "_custom_data": {"type": dict}, + } + system_name: SystemName + """ + LLDP system name (LLDP TLV 5) av-pair. + + Subclass of AvdModel. + """ + system_description: SystemDescription + """ + LLDP system description (LLDP TLV 6) av-pair. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + system_name: SystemName | UndefinedType = Undefined, + system_description: SystemDescription | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Lldp. + + + Subclass of AvdModel. + + Args: + system_name: + LLDP system name (LLDP TLV 5) av-pair. + + Subclass of AvdModel. + system_description: + LLDP system description (LLDP TLV 6) av-pair. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Dhcp(AvdModel): + """Subclass of AvdModel.""" + + class Hostname(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "auth_only": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool + auth_only: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + auth_only: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Hostname. + + + Subclass of AvdModel. + + Args: + enabled: enabled + auth_only: auth_only + _custom_data: _custom_data + + """ + + class ParameterRequestList(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "auth_only": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool + auth_only: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + auth_only: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ParameterRequestList. + + + Subclass of AvdModel. + + Args: + enabled: enabled + auth_only: auth_only + _custom_data: _custom_data + + """ + + class VendorClassId(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "auth_only": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool + auth_only: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + auth_only: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VendorClassId. + + + Subclass of AvdModel. + + Args: + enabled: enabled + auth_only: auth_only + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "hostname": {"type": Hostname}, + "parameter_request_list": {"type": ParameterRequestList}, + "vendor_class_id": {"type": VendorClassId}, + "_custom_data": {"type": dict}, + } + hostname: Hostname + """ + Hostname (DHCP Option 12). + + Subclass of AvdModel. + """ + parameter_request_list: ParameterRequestList + """ + Parameters requested by host (DHCP Option 55). + + Subclass of AvdModel. + """ + vendor_class_id: VendorClassId + """ + Vendor class identifier (DHCP Option 60). + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: Hostname | UndefinedType = Undefined, + parameter_request_list: ParameterRequestList | UndefinedType = Undefined, + vendor_class_id: VendorClassId | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dhcp. + + + Subclass of AvdModel. + + Args: + hostname: + Hostname (DHCP Option 12). + + Subclass of AvdModel. + parameter_request_list: + Parameters requested by host (DHCP Option 55). + + Subclass of AvdModel. + vendor_class_id: + Vendor class identifier (DHCP Option 60). + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "service_type": {"type": bool}, + "framed_mtu": {"type": int}, + "lldp": {"type": Lldp}, + "dhcp": {"type": Dhcp}, + "_custom_data": {"type": dict}, + } + service_type: bool | None + framed_mtu: int | None + lldp: Lldp + """Subclass of AvdModel.""" + dhcp: Dhcp + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + service_type: bool | None | UndefinedType = Undefined, + framed_mtu: int | None | UndefinedType = Undefined, + lldp: Lldp | UndefinedType = Undefined, + dhcp: Dhcp | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RadiusAvPair. + + + Subclass of AvdModel. + + Args: + service_type: service_type + framed_mtu: framed_mtu + lldp: Subclass of AvdModel. + dhcp: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Aaa(AvdModel): + """Subclass of AvdModel.""" + + class Unresponsive(AvdModel): + """Subclass of AvdModel.""" + + class Action(AvdModel): + """Subclass of AvdModel.""" + + class CachedResultsTimeout(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"time_duration": {"type": int}, "time_duration_unit": {"type": str}, "_custom_data": {"type": dict}} + time_duration: int | None + """ + Enable caching for a specific duration - + <1-10000> duration in days + <1-14400000> duration in + minutes + <1-240000> duration in hours + <1-864000000> duration in seconds + """ + time_duration_unit: Literal["days", "hours", "minutes", "seconds"] + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + time_duration: int | None | UndefinedType = Undefined, + time_duration_unit: Literal["days", "hours", "minutes", "seconds"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CachedResultsTimeout. + + + Subclass of AvdModel. + + Args: + time_duration: + Enable caching for a specific duration - + <1-10000> duration in days + <1-14400000> duration in + minutes + <1-240000> duration in hours + <1-864000000> duration in seconds + time_duration_unit: time_duration_unit + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "apply_cached_results": {"type": bool}, + "cached_results_timeout": {"type": CachedResultsTimeout}, + "apply_alternate": {"type": bool}, + "traffic_allow": {"type": bool}, + "traffic_allow_vlan": {"type": int}, + "_custom_data": {"type": dict}, + } + apply_cached_results: bool | None + """Use results from a previous AAA response.""" + cached_results_timeout: CachedResultsTimeout + """Subclass of AvdModel.""" + apply_alternate: bool | None + """ + Apply alternate action if primary action fails. + eg. aaa unresponsive action apply cached-results + else traffic allow + """ + traffic_allow: bool | None + """Set action for supplicant traffic when AAA times out.""" + traffic_allow_vlan: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + apply_cached_results: bool | None | UndefinedType = Undefined, + cached_results_timeout: CachedResultsTimeout | UndefinedType = Undefined, + apply_alternate: bool | None | UndefinedType = Undefined, + traffic_allow: bool | None | UndefinedType = Undefined, + traffic_allow_vlan: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Action. + + + Subclass of AvdModel. + + Args: + apply_cached_results: Use results from a previous AAA response. + cached_results_timeout: Subclass of AvdModel. + apply_alternate: + Apply alternate action if primary action fails. + eg. aaa unresponsive action apply cached-results + else traffic allow + traffic_allow: Set action for supplicant traffic when AAA times out. + traffic_allow_vlan: traffic_allow_vlan + _custom_data: _custom_data + + """ + + class PhoneAction(AvdModel): + """Subclass of AvdModel.""" + + class CachedResultsTimeout(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"time_duration": {"type": int}, "time_duration_unit": {"type": str}, "_custom_data": {"type": dict}} + time_duration: int | None + """ + Enable caching for a specific duration - + <1-10000> duration in days + <1-14400000> duration in + minutes + <1-240000> duration in hours + <1-864000000> duration in seconds + """ + time_duration_unit: Literal["days", "hours", "minutes", "seconds"] + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + time_duration: int | None | UndefinedType = Undefined, + time_duration_unit: Literal["days", "hours", "minutes", "seconds"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CachedResultsTimeout. + + + Subclass of AvdModel. + + Args: + time_duration: + Enable caching for a specific duration - + <1-10000> duration in days + <1-14400000> duration in + minutes + <1-240000> duration in hours + <1-864000000> duration in seconds + time_duration_unit: time_duration_unit + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "apply_cached_results": {"type": bool}, + "cached_results_timeout": {"type": CachedResultsTimeout}, + "apply_alternate": {"type": bool}, + "traffic_allow": {"type": bool}, + "_custom_data": {"type": dict}, + } + apply_cached_results: bool | None + """Use results from a previous AAA response.""" + cached_results_timeout: CachedResultsTimeout + """Subclass of AvdModel.""" + apply_alternate: bool | None + """ + Apply alternate action if primary action fails. + eg. aaa unresponsive phone action apply cached- + results else traffic allow + """ + traffic_allow: bool | None + """Set action for supplicant traffic when AAA times out.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + apply_cached_results: bool | None | UndefinedType = Undefined, + cached_results_timeout: CachedResultsTimeout | UndefinedType = Undefined, + apply_alternate: bool | None | UndefinedType = Undefined, + traffic_allow: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PhoneAction. + + + Subclass of AvdModel. + + Args: + apply_cached_results: Use results from a previous AAA response. + cached_results_timeout: Subclass of AvdModel. + apply_alternate: + Apply alternate action if primary action fails. + eg. aaa unresponsive phone action apply cached- + results else traffic allow + traffic_allow: Set action for supplicant traffic when AAA times out. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "eap_response": {"type": str}, + "action": {"type": Action}, + "phone_action": {"type": PhoneAction}, + "recovery_action_reauthenticate": {"type": bool}, + "_custom_data": {"type": dict}, + } + eap_response: Literal["success", "disabled"] | None + """EAP response to send.""" + action: Action + """ + Set action for supplicant when AAA times out. + + Subclass of AvdModel. + """ + phone_action: PhoneAction + """ + Set action for supplicant when AAA times out. + + Subclass of AvdModel. + """ + recovery_action_reauthenticate: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + eap_response: Literal["success", "disabled"] | None | UndefinedType = Undefined, + action: Action | UndefinedType = Undefined, + phone_action: PhoneAction | UndefinedType = Undefined, + recovery_action_reauthenticate: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Unresponsive. + + + Subclass of AvdModel. + + Args: + eap_response: EAP response to send. + action: + Set action for supplicant when AAA times out. + + Subclass of AvdModel. + phone_action: + Set action for supplicant when AAA times out. + + Subclass of AvdModel. + recovery_action_reauthenticate: recovery_action_reauthenticate + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"unresponsive": {"type": Unresponsive}, "accounting_update_interval": {"type": int}, "_custom_data": {"type": dict}} + unresponsive: Unresponsive + """ + Configure AAA timeout options. + + Subclass of AvdModel. + """ + accounting_update_interval: int | None + """Interval period in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + unresponsive: Unresponsive | UndefinedType = Undefined, + accounting_update_interval: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Aaa. + + + Subclass of AvdModel. + + Args: + unresponsive: + Configure AAA timeout options. + + Subclass of AvdModel. + accounting_update_interval: Interval period in seconds. + _custom_data: _custom_data + + """ + + class CaptivePortal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "url": {"type": str}, + "ssl_profile": {"type": str}, + "start_limit_infinite": {"type": bool}, + "access_list_ipv4": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool + url: str | None + """ + Supported URL type: + - http: http://[:] + - https: https://[:] + """ + ssl_profile: str | None + start_limit_infinite: bool | None + """Set captive-portal start limit to infinite.""" + access_list_ipv4: str | None + """Standard access-list name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + url: str | None | UndefinedType = Undefined, + ssl_profile: str | None | UndefinedType = Undefined, + start_limit_infinite: bool | None | UndefinedType = Undefined, + access_list_ipv4: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CaptivePortal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + url: + Supported URL type: + - http: http://[:] + - https: https://[:] + ssl_profile: ssl_profile + start_limit_infinite: Set captive-portal start limit to infinite. + access_list_ipv4: Standard access-list name. + _custom_data: _custom_data + + """ + + class Supplicant(AvdModel): + """Subclass of AvdModel.""" + + class ProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "eap_method": {"type": str}, + "identity": {"type": str}, + "passphrase_type": {"type": str, "default": "7"}, + "passphrase": {"type": str}, + "ssl_profile": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + eap_method: Literal["fast", "tls"] | None + """ + Extensible Authentication Protocol method: + - EAP Flexible Authentication via Secure Tunneling. + - + EAP with Transport Layer Security. + """ + identity: str | None + """User identity.""" + passphrase_type: Literal["0", "7", "8a"] + """Default value: `"7"`""" + passphrase: str | None + """Extensible Authentication Protocol password.""" + ssl_profile: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + eap_method: Literal["fast", "tls"] | None | UndefinedType = Undefined, + identity: str | None | UndefinedType = Undefined, + passphrase_type: Literal["0", "7", "8a"] | UndefinedType = Undefined, + passphrase: str | None | UndefinedType = Undefined, + ssl_profile: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ProfilesItem. + + + Subclass of AvdModel. + + Args: + name: name + eap_method: + Extensible Authentication Protocol method: + - EAP Flexible Authentication via Secure Tunneling. + - + EAP with Transport Layer Security. + identity: User identity. + passphrase_type: passphrase_type + passphrase: Extensible Authentication Protocol password. + ssl_profile: ssl_profile + _custom_data: _custom_data + + """ + + class Profiles(AvdIndexedList[str, ProfilesItem]): + """Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Profiles._item_type = ProfilesItem + + _fields: ClassVar[dict] = { + "profiles": {"type": Profiles}, + "logging": {"type": bool}, + "disconnect_cached_results_timeout": {"type": int}, + "_custom_data": {"type": dict}, + } + profiles: Profiles + """ + Dot1x supplicant profiles. + + Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is + `name` (`str`). + """ + logging: bool | None + """Enable supplicant logging.""" + disconnect_cached_results_timeout: int | None + """Timeout in seconds for removing a disconnected supplicant.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profiles: Profiles | UndefinedType = Undefined, + logging: bool | None | UndefinedType = Undefined, + disconnect_cached_results_timeout: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Supplicant. + + + Subclass of AvdModel. + + Args: + profiles: + Dot1x supplicant profiles. + + Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is + `name` (`str`). + logging: Enable supplicant logging. + disconnect_cached_results_timeout: Timeout in seconds for removing a disconnected supplicant. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "system_auth_control": {"type": bool}, + "protocol_lldp_bypass": {"type": bool}, + "protocol_bpdu_bypass": {"type": bool}, + "dynamic_authorization": {"type": bool}, + "mac_based_authentication": {"type": MacBasedAuthentication}, + "radius_av_pair_username_format": {"type": RadiusAvPairUsernameFormat}, + "radius_av_pair": {"type": RadiusAvPair}, + "aaa": {"type": Aaa}, + "captive_portal": {"type": CaptivePortal}, + "supplicant": {"type": Supplicant}, + "_custom_data": {"type": dict}, + } + system_auth_control: bool | None + protocol_lldp_bypass: bool | None + protocol_bpdu_bypass: bool | None + dynamic_authorization: bool | None + mac_based_authentication: MacBasedAuthentication + """Subclass of AvdModel.""" + radius_av_pair_username_format: RadiusAvPairUsernameFormat + """ + RADIUS AV-pair username settings. + + Subclass of AvdModel. + """ + radius_av_pair: RadiusAvPair + """Subclass of AvdModel.""" + aaa: Aaa + """ + Configure AAA parameters. + + Subclass of AvdModel. + """ + captive_portal: CaptivePortal + """ + Web authentication feature authenticates a supplicant through a web page, referred to as a captive + portal. + + Subclass of AvdModel. + """ + supplicant: Supplicant + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + system_auth_control: bool | None | UndefinedType = Undefined, + protocol_lldp_bypass: bool | None | UndefinedType = Undefined, + protocol_bpdu_bypass: bool | None | UndefinedType = Undefined, + dynamic_authorization: bool | None | UndefinedType = Undefined, + mac_based_authentication: MacBasedAuthentication | UndefinedType = Undefined, + radius_av_pair_username_format: RadiusAvPairUsernameFormat | UndefinedType = Undefined, + radius_av_pair: RadiusAvPair | UndefinedType = Undefined, + aaa: Aaa | UndefinedType = Undefined, + captive_portal: CaptivePortal | UndefinedType = Undefined, + supplicant: Supplicant | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dot1x. + + + Subclass of AvdModel. + + Args: + system_auth_control: system_auth_control + protocol_lldp_bypass: protocol_lldp_bypass + protocol_bpdu_bypass: protocol_bpdu_bypass + dynamic_authorization: dynamic_authorization + mac_based_authentication: Subclass of AvdModel. + radius_av_pair_username_format: + RADIUS AV-pair username settings. + + Subclass of AvdModel. + radius_av_pair: Subclass of AvdModel. + aaa: + Configure AAA parameters. + + Subclass of AvdModel. + captive_portal: + Web authentication feature authenticates a supplicant through a web page, referred to as a captive + portal. + + Subclass of AvdModel. + supplicant: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class DpsInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class FlowTracker(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"sampled": {"type": str}, "hardware": {"type": str}, "_custom_data": {"type": dict}} + sampled: str | None + """Sampled flow tracker name.""" + hardware: str | None + """Hardware flow tracker name,""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sampled: str | None | UndefinedType = Undefined, + hardware: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracker. + + + Subclass of AvdModel. + + Args: + sampled: Sampled flow tracker name. + hardware: Hardware flow tracker name, + _custom_data: _custom_data + + """ + + class TcpMssCeiling(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4": {"type": int}, "ipv6": {"type": int}, "direction": {"type": str}, "_custom_data": {"type": dict}} + ipv4: int | None + """Segment Size for IPv4.""" + ipv6: int | None + """Segment Size for IPv6.""" + direction: Literal["ingress", "egress"] | None + """Optional direction ('ingress', 'egress') for tcp mss ceiling.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4: int | None | UndefinedType = Undefined, + ipv6: int | None | UndefinedType = Undefined, + direction: Literal["ingress", "egress"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TcpMssCeiling. + + + Subclass of AvdModel. + + Args: + ipv4: Segment Size for IPv4. + ipv6: Segment Size for IPv6. + direction: Optional direction ('ingress', 'egress') for tcp mss ceiling. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "description": {"type": str}, + "shutdown": {"type": bool}, + "mtu": {"type": int}, + "ip_address": {"type": str}, + "flow_tracker": {"type": FlowTracker}, + "tcp_mss_ceiling": {"type": TcpMssCeiling}, + "eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + name: Literal["Dps1"] + """"Dps1" is currently the only supported interface.""" + description: str | None + shutdown: bool | None + mtu: int | None + """Maximum Transmission Unit in bytes.""" + ip_address: str | None + """IPv4 address/mask.""" + flow_tracker: FlowTracker + """Subclass of AvdModel.""" + tcp_mss_ceiling: TcpMssCeiling + """Subclass of AvdModel.""" + eos_cli: str | None + """Multiline String with EOS CLI rendered directly on the Dps interface in the final EOS configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: Literal["Dps1"] | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + flow_tracker: FlowTracker | UndefinedType = Undefined, + tcp_mss_ceiling: TcpMssCeiling | UndefinedType = Undefined, + eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DpsInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: "Dps1" is currently the only supported interface. + description: description + shutdown: shutdown + mtu: Maximum Transmission Unit in bytes. + ip_address: IPv4 address/mask. + flow_tracker: Subclass of AvdModel. + tcp_mss_ceiling: Subclass of AvdModel. + eos_cli: Multiline String with EOS CLI rendered directly on the Dps interface in the final EOS configuration. + _custom_data: _custom_data + + """ + + class DpsInterfaces(AvdIndexedList[str, DpsInterfacesItem]): + """Subclass of AvdIndexedList with `DpsInterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + DpsInterfaces._item_type = DpsInterfacesItem + + class DynamicPrefixListsItem(AvdModel): + """Subclass of AvdModel.""" + + class PrefixList(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4": {"type": str}, "ipv6": {"type": str}, "_custom_data": {"type": dict}} + ipv4: str | None + """Prefix-list name.""" + ipv6: str | None + """Prefix-list name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4: str | None | UndefinedType = Undefined, + ipv6: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PrefixList. + + + Subclass of AvdModel. + + Args: + ipv4: Prefix-list name. + ipv6: Prefix-list name. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"name": {"type": str}, "match_map": {"type": str}, "prefix_list": {"type": PrefixList}, "_custom_data": {"type": dict}} + name: str | None + """Dynamic prefix-list name.""" + match_map: str | None + """Route-map name.""" + prefix_list: PrefixList + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + match_map: str | None | UndefinedType = Undefined, + prefix_list: PrefixList | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DynamicPrefixListsItem. + + + Subclass of AvdModel. + + Args: + name: Dynamic prefix-list name. + match_map: Route-map name. + prefix_list: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class DynamicPrefixLists(AvdList[DynamicPrefixListsItem]): + """Subclass of AvdList with `DynamicPrefixListsItem` items.""" + + DynamicPrefixLists._item_type = DynamicPrefixListsItem + + class EnablePassword(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"disabled": {"type": bool}, "hash_algorithm": {"type": str}, "key": {"type": str}, "_custom_data": {"type": dict}} + disabled: bool | None + """Set to `true` to configure `no enable password` which is the EOS default.""" + hash_algorithm: Literal["md5", "sha512"] | None + key: str | None + """ + Must be the hash of the password using the specified algorithm. + By default EOS salts the password, + so the simplest is to generate the hash on an EOS device. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + disabled: bool | None | UndefinedType = Undefined, + hash_algorithm: Literal["md5", "sha512"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EnablePassword. + + + Subclass of AvdModel. + + Args: + disabled: Set to `true` to configure `no enable password` which is the EOS default. + hash_algorithm: hash_algorithm + key: + Must be the hash of the password using the specified algorithm. + By default EOS salts the password, + so the simplest is to generate the hash on an EOS device. + _custom_data: _custom_data + + """ + + class EosCliConfigGenConfiguration(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enable": {"type": bool, "default": True}, + "hide_passwords": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + enable: bool + """ + Generate device EOS configurations. + + Default value: `True` + """ + hide_passwords: bool + """ + Replace the input data using the `hide_passwords` filter in the Jinja2 templates by '' in + the configuration if true. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enable: bool | UndefinedType = Undefined, + hide_passwords: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EosCliConfigGenConfiguration. + + + Subclass of AvdModel. + + Args: + enable: Generate device EOS configurations. + hide_passwords: + Replace the input data using the `hide_passwords` filter in the Jinja2 templates by '' in + the configuration if true. + _custom_data: _custom_data + + """ + + class EosCliConfigGenDocumentation(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enable": {"type": bool, "default": True}, "hide_passwords": {"type": bool, "default": True}, "_custom_data": {"type": dict}} + enable: bool + """ + Generate device Markdown documentation. + + Default value: `True` + """ + hide_passwords: bool + """ + Replace the input data using the `hide_passwords` filter in the Jinja2 templates by '' in + the documentation if true. + + Default value: `True` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enable: bool | UndefinedType = Undefined, + hide_passwords: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EosCliConfigGenDocumentation. + + + Subclass of AvdModel. + + Args: + enable: Generate device Markdown documentation. + hide_passwords: + Replace the input data using the `hide_passwords` filter in the Jinja2 templates by '' in + the documentation if true. + _custom_data: _custom_data + + """ + + class Errdisable(AvdModel): + """Subclass of AvdModel.""" + + class Detect(AvdModel): + """Subclass of AvdModel.""" + + class Causes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Causes._item_type = str + + _fields: ClassVar[dict] = {"causes": {"type": Causes}, "_custom_data": {"type": dict}} + causes: Causes + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, causes: Causes | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Detect. + + + Subclass of AvdModel. + + Args: + causes: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class Recovery(AvdModel): + """Subclass of AvdModel.""" + + class Causes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Causes._item_type = str + + _fields: ClassVar[dict] = {"causes": {"type": Causes}, "interval": {"type": int, "default": 300}, "_custom_data": {"type": dict}} + causes: Causes + """Subclass of AvdList with `str` items.""" + interval: int + """ + Interval in seconds. + + Default value: `300` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + causes: Causes | UndefinedType = Undefined, + interval: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Recovery. + + + Subclass of AvdModel. + + Args: + causes: Subclass of AvdList with `str` items. + interval: Interval in seconds. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"detect": {"type": Detect}, "recovery": {"type": Recovery}, "_custom_data": {"type": dict}} + detect: Detect + """Subclass of AvdModel.""" + recovery: Recovery + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + detect: Detect | UndefinedType = Undefined, + recovery: Recovery | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Errdisable. + + + Subclass of AvdModel. + + Args: + detect: Subclass of AvdModel. + recovery: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class EthernetInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Phone(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"trunk": {"type": str}, "vlan": {"type": int}, "_custom_data": {"type": dict}} + trunk: Literal["tagged", "tagged phone", "untagged", "untagged phone"] | None + vlan: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + trunk: Literal["tagged", "tagged phone", "untagged", "untagged phone"] | None | UndefinedType = Undefined, + vlan: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Phone. + + + Subclass of AvdModel. + + Args: + trunk: trunk + vlan: vlan + _custom_data: _custom_data + + """ + + class L2Protocol(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"encapsulation_dot1q_vlan": {"type": int}, "forwarding_profile": {"type": str}, "_custom_data": {"type": dict}} + encapsulation_dot1q_vlan: int | None + """Vlan tag to configure on sub-interface.""" + forwarding_profile: str | None + """L2 protocol forwarding profile.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + encapsulation_dot1q_vlan: int | None | UndefinedType = Undefined, + forwarding_profile: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L2Protocol. + + + Subclass of AvdModel. + + Args: + encapsulation_dot1q_vlan: Vlan tag to configure on sub-interface. + forwarding_profile: L2 protocol forwarding profile. + _custom_data: _custom_data + + """ + + class TrunkGroups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + TrunkGroups._item_type = str + + class AddressLocking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4": {"type": bool}, "ipv6": {"type": bool}, "_custom_data": {"type": dict}} + ipv4: bool | None + """Enable address locking for IPv4.""" + ipv6: bool | None + """Enable address locking for IPv6.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4: bool | None | UndefinedType = Undefined, + ipv6: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressLocking. + + + Subclass of AvdModel. + + Args: + ipv4: Enable address locking for IPv4. + ipv6: Enable address locking for IPv6. + _custom_data: _custom_data + + """ + + class Flowcontrol(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"received": {"type": str}, "_custom_data": {"type": dict}} + received: Literal["desired", "on", "off"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + received: Literal["desired", "on", "off"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Flowcontrol. + + + Subclass of AvdModel. + + Args: + received: received + _custom_data: _custom_data + + """ + + class FlowTracker(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"sampled": {"type": str}, "hardware": {"type": str}, "_custom_data": {"type": dict}} + sampled: str | None + """Sampled flow tracker name.""" + hardware: str | None + """Hardware flow tracker name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sampled: str | None | UndefinedType = Undefined, + hardware: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracker. + + + Subclass of AvdModel. + + Args: + sampled: Sampled flow tracker name. + hardware: Hardware flow tracker name. + _custom_data: _custom_data + + """ + + class ErrorCorrectionEncoding(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "fire_code": {"type": bool}, + "reed_solomon": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + fire_code: bool | None + reed_solomon: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + fire_code: bool | None | UndefinedType = Undefined, + reed_solomon: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ErrorCorrectionEncoding. + + + Subclass of AvdModel. + + Args: + enabled: enabled + fire_code: fire_code + reed_solomon: reed_solomon + _custom_data: _custom_data + + """ + + class LinkTrackingGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "direction": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Group name.""" + direction: Literal["upstream", "downstream"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + direction: Literal["upstream", "downstream"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkTrackingGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Group name. + direction: direction + _custom_data: _custom_data + + """ + + class LinkTrackingGroups(AvdIndexedList[str, LinkTrackingGroupsItem]): + """Subclass of AvdIndexedList with `LinkTrackingGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + LinkTrackingGroups._item_type = LinkTrackingGroupsItem + + class LinkTracking(AvdModel): + """Subclass of AvdModel.""" + + class Groups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Groups._item_type = str + + _fields: ClassVar[dict] = {"direction": {"type": str}, "groups": {"type": Groups}, "_custom_data": {"type": dict}} + direction: Literal["upstream", "downstream"] | None + groups: Groups + """ + Link state group(s) an interface belongs to. + + Subclass of AvdList with `str` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction: Literal["upstream", "downstream"] | None | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkTracking. + + + Subclass of AvdModel. + + Args: + direction: direction + groups: + Link state group(s) an interface belongs to. + + Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class EvpnEthernetSegment(AvdModel): + """Subclass of AvdModel.""" + + class DesignatedForwarderElection(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "algorithm": {"type": str}, + "preference_value": {"type": int}, + "dont_preempt": {"type": bool}, + "hold_time": {"type": int}, + "subsequent_hold_time": {"type": int}, + "candidate_reachability_required": {"type": bool}, + "_custom_data": {"type": dict}, + } + algorithm: Literal["modulus", "preference"] | None + preference_value: int | None + """Preference_value is only used when "algorithm" is "preference".""" + dont_preempt: bool | None + """Dont_preempt is only used when "algorithm" is "preference".""" + hold_time: int | None + subsequent_hold_time: int | None + candidate_reachability_required: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + algorithm: Literal["modulus", "preference"] | None | UndefinedType = Undefined, + preference_value: int | None | UndefinedType = Undefined, + dont_preempt: bool | None | UndefinedType = Undefined, + hold_time: int | None | UndefinedType = Undefined, + subsequent_hold_time: int | None | UndefinedType = Undefined, + candidate_reachability_required: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DesignatedForwarderElection. + + + Subclass of AvdModel. + + Args: + algorithm: algorithm + preference_value: Preference_value is only used when "algorithm" is "preference". + dont_preempt: Dont_preempt is only used when "algorithm" is "preference". + hold_time: hold_time + subsequent_hold_time: subsequent_hold_time + candidate_reachability_required: candidate_reachability_required + _custom_data: _custom_data + + """ + + class Mpls(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"shared_index": {"type": int}, "tunnel_flood_filter_time": {"type": int}, "_custom_data": {"type": dict}} + shared_index: int | None + tunnel_flood_filter_time: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + shared_index: int | None | UndefinedType = Undefined, + tunnel_flood_filter_time: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Mpls. + + + Subclass of AvdModel. + + Args: + shared_index: shared_index + tunnel_flood_filter_time: tunnel_flood_filter_time + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "identifier": {"type": str}, + "redundancy": {"type": str}, + "designated_forwarder_election": {"type": DesignatedForwarderElection}, + "mpls": {"type": Mpls}, + "route_target": {"type": str}, + "_custom_data": {"type": dict}, + } + identifier: str | None + """EVPN Ethernet Segment Identifier (Type 1 format).""" + redundancy: Literal["all-active", "single-active"] | None + designated_forwarder_election: DesignatedForwarderElection + """Subclass of AvdModel.""" + mpls: Mpls + """Subclass of AvdModel.""" + route_target: str | None + """EVPN Route Target for ESI with format xx:xx:xx:xx:xx:xx.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + identifier: str | None | UndefinedType = Undefined, + redundancy: Literal["all-active", "single-active"] | None | UndefinedType = Undefined, + designated_forwarder_election: DesignatedForwarderElection | UndefinedType = Undefined, + mpls: Mpls | UndefinedType = Undefined, + route_target: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnEthernetSegment. + + + Subclass of AvdModel. + + Args: + identifier: EVPN Ethernet Segment Identifier (Type 1 format). + redundancy: redundancy + designated_forwarder_election: Subclass of AvdModel. + mpls: Subclass of AvdModel. + route_target: EVPN Route Target for ESI with format xx:xx:xx:xx:xx:xx. + _custom_data: _custom_data + + """ + + class EncapsulationDot1q(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"vlan": {"type": int}, "inner_vlan": {"type": int}, "_custom_data": {"type": dict}} + vlan: int + """VLAD ID.""" + inner_vlan: int | None + """Inner VLAN ID. This setting can only be applied to sub-interfaces on EOS.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + vlan: int | UndefinedType = Undefined, + inner_vlan: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EncapsulationDot1q. + + + Subclass of AvdModel. + + Args: + vlan: VLAD ID. + inner_vlan: Inner VLAN ID. This setting can only be applied to sub-interfaces on EOS. + _custom_data: _custom_data + + """ + + class EncapsulationVlan(AvdModel): + """Subclass of AvdModel.""" + + class Client(AvdModel): + """Subclass of AvdModel.""" + + class Dot1q(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"vlan": {"type": int}, "outer": {"type": int}, "inner": {"type": int}, "_custom_data": {"type": dict}} + vlan: int | None + """Client VLAN ID.""" + outer: int | None + """Client Outer VLAN ID.""" + inner: int | None + """Client Inner VLAN ID.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + vlan: int | None | UndefinedType = Undefined, + outer: int | None | UndefinedType = Undefined, + inner: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dot1q. + + + Subclass of AvdModel. + + Args: + vlan: Client VLAN ID. + outer: Client Outer VLAN ID. + inner: Client Inner VLAN ID. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "dot1q": {"type": Dot1q}, + "unmatched": {"type": bool}, + "encapsulation": {"type": str}, + "vlan": {"type": int}, + "outer_vlan": {"type": int}, + "inner_vlan": {"type": int}, + "inner_encapsulation": {"type": str}, + "_custom_data": {"type": dict}, + } + dot1q: Dot1q + """Subclass of AvdModel.""" + unmatched: bool | None + encapsulation: Literal["dot1q", "dot1ad", "unmatched", "untagged"] | None + vlan: int | None + """Client VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: unmatched`.""" + outer_vlan: int | None + """Client Outer VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: unmatched`.""" + inner_vlan: int | None + """Client Inner VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: unmatched`.""" + inner_encapsulation: Literal["dot1q", "dot1ad"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dot1q: Dot1q | UndefinedType = Undefined, + unmatched: bool | None | UndefinedType = Undefined, + encapsulation: Literal["dot1q", "dot1ad", "unmatched", "untagged"] | None | UndefinedType = Undefined, + vlan: int | None | UndefinedType = Undefined, + outer_vlan: int | None | UndefinedType = Undefined, + inner_vlan: int | None | UndefinedType = Undefined, + inner_encapsulation: Literal["dot1q", "dot1ad"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Client. + + + Subclass of AvdModel. + + Args: + dot1q: Subclass of AvdModel. + unmatched: unmatched + encapsulation: encapsulation + vlan: Client VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: unmatched`. + outer_vlan: Client Outer VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: unmatched`. + inner_vlan: Client Inner VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: unmatched`. + inner_encapsulation: inner_encapsulation + _custom_data: _custom_data + + """ + + class Network(AvdModel): + """Subclass of AvdModel.""" + + class Dot1q(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"vlan": {"type": int}, "outer": {"type": int}, "inner": {"type": int}, "_custom_data": {"type": dict}} + vlan: int | None + """Network VLAN ID.""" + outer: int | None + """Network outer VLAN ID.""" + inner: int | None + """Network inner VLAN ID.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + vlan: int | None | UndefinedType = Undefined, + outer: int | None | UndefinedType = Undefined, + inner: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dot1q. + + + Subclass of AvdModel. + + Args: + vlan: Network VLAN ID. + outer: Network outer VLAN ID. + inner: Network inner VLAN ID. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "dot1q": {"type": Dot1q}, + "client": {"type": bool}, + "encapsulation": {"type": str}, + "vlan": {"type": int}, + "outer_vlan": {"type": int}, + "inner_vlan": {"type": int}, + "inner_encapsulation": {"type": str}, + "_custom_data": {"type": dict}, + } + dot1q: Dot1q + """Subclass of AvdModel.""" + client: bool | None + encapsulation: Literal["dot1q", "dot1ad", "client", "client inner", "untagged"] | None + """ + `untagged` (no encapsulation) is applicable for `untagged` client only. + `client` and `client inner` + (retain client encapsulation) is not applicable for `untagged` client. + """ + vlan: int | None + """Network VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: client`.""" + outer_vlan: int | None + """Network outer VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: client`.""" + inner_vlan: int | None + """Network inner VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: client`.""" + inner_encapsulation: Literal["dot1q", "dot1ad"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dot1q: Dot1q | UndefinedType = Undefined, + client: bool | None | UndefinedType = Undefined, + encapsulation: Literal["dot1q", "dot1ad", "client", "client inner", "untagged"] | None | UndefinedType = Undefined, + vlan: int | None | UndefinedType = Undefined, + outer_vlan: int | None | UndefinedType = Undefined, + inner_vlan: int | None | UndefinedType = Undefined, + inner_encapsulation: Literal["dot1q", "dot1ad"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Network. + + + Subclass of AvdModel. + + Args: + dot1q: Subclass of AvdModel. + client: client + encapsulation: + `untagged` (no encapsulation) is applicable for `untagged` client only. + `client` and `client inner` + (retain client encapsulation) is not applicable for `untagged` client. + vlan: Network VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: client`. + outer_vlan: Network outer VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: client`. + inner_vlan: Network inner VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: client`. + inner_encapsulation: inner_encapsulation + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"client": {"type": Client}, "network": {"type": Network}, "_custom_data": {"type": dict}} + client: Client + """Subclass of AvdModel.""" + network: Network + """ + Network encapsulations are all optional and skipped if using client unmatched. + + Subclass of + AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + client: Client | UndefinedType = Undefined, + network: Network | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EncapsulationVlan. + + + Subclass of AvdModel. + + Args: + client: Subclass of AvdModel. + network: + Network encapsulations are all optional and skipped if using client unmatched. + + Subclass of + AvdModel. + _custom_data: _custom_data + + """ + + class IpAddressSecondaries(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + IpAddressSecondaries._item_type = str + + class IpHelpersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ip_helper": {"type": str}, "source_interface": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + ip_helper: str + source_interface: str | None + """Source interface name.""" + vrf: str | None + """VRF name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_helper: str | UndefinedType = Undefined, + source_interface: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpHelpersItem. + + + Subclass of AvdModel. + + Args: + ip_helper: ip_helper + source_interface: Source interface name. + vrf: VRF name. + _custom_data: _custom_data + + """ + + class IpHelpers(AvdIndexedList[str, IpHelpersItem]): + """Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is `ip_helper` (`str`).""" + + _primary_key: ClassVar[str] = "ip_helper" + + IpHelpers._item_type = IpHelpersItem + + class IpNat(AvdModel): + """Subclass of AvdModel.""" + + class Destination(AvdModel): + """Subclass of AvdModel.""" + + class DynamicItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "access_list": {"type": str}, + "comment": {"type": str}, + "pool_name": {"type": str}, + "priority": {"type": int}, + "_custom_data": {"type": dict}, + } + access_list: str + comment: str | None + pool_name: str + priority: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + access_list: str | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + pool_name: str | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DynamicItem. + + + Subclass of AvdModel. + + Args: + access_list: access_list + comment: comment + pool_name: pool_name + priority: priority + _custom_data: _custom_data + + """ + + class Dynamic(AvdIndexedList[str, DynamicItem]): + """Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`).""" + + _primary_key: ClassVar[str] = "access_list" + + Dynamic._item_type = DynamicItem + + class StaticItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "access_list": {"type": str}, + "comment": {"type": str}, + "direction": {"type": str}, + "group": {"type": int}, + "original_ip": {"type": str}, + "original_port": {"type": int}, + "priority": {"type": int}, + "protocol": {"type": str}, + "translated_ip": {"type": str}, + "translated_port": {"type": int}, + "_custom_data": {"type": dict}, + } + access_list: str | None + """'access_list' and 'group' are mutual exclusive.""" + comment: str | None + direction: Literal["egress", "ingress"] | None + """ + Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware + platform. + EOS might remove this keyword in the configuration. So, check the configuration on + targeted HW/SW. + """ + group: int | None + """'access_list' and 'group' are mutual exclusive.""" + original_ip: str | None + """IPv4 address. The combination of `original_ip` and `original_port` must be unique.""" + original_port: int | None + """TCP/UDP port. The combination of `original_ip` and `original_port` must be unique.""" + priority: int | None + protocol: Literal["udp", "tcp"] | None + translated_ip: str + """IPv4 address.""" + translated_port: int | None + """requires 'original_port'.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + access_list: str | None | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + direction: Literal["egress", "ingress"] | None | UndefinedType = Undefined, + group: int | None | UndefinedType = Undefined, + original_ip: str | None | UndefinedType = Undefined, + original_port: int | None | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + protocol: Literal["udp", "tcp"] | None | UndefinedType = Undefined, + translated_ip: str | UndefinedType = Undefined, + translated_port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StaticItem. + + + Subclass of AvdModel. + + Args: + access_list: 'access_list' and 'group' are mutual exclusive. + comment: comment + direction: + Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware + platform. + EOS might remove this keyword in the configuration. So, check the configuration on + targeted HW/SW. + group: 'access_list' and 'group' are mutual exclusive. + original_ip: IPv4 address. The combination of `original_ip` and `original_port` must be unique. + original_port: TCP/UDP port. The combination of `original_ip` and `original_port` must be unique. + priority: priority + protocol: protocol + translated_ip: IPv4 address. + translated_port: requires 'original_port'. + _custom_data: _custom_data + + """ + + class Static(AvdList[StaticItem]): + """Subclass of AvdList with `StaticItem` items.""" + + Static._item_type = StaticItem + + _fields: ClassVar[dict] = {"dynamic": {"type": Dynamic}, "static": {"type": Static}, "_custom_data": {"type": dict}} + dynamic: Dynamic + """Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`).""" + static: Static + """Subclass of AvdList with `StaticItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dynamic: Dynamic | UndefinedType = Undefined, + static: Static | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Destination. + + + Subclass of AvdModel. + + Args: + dynamic: Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`). + static: Subclass of AvdList with `StaticItem` items. + _custom_data: _custom_data + + """ + + class Source(AvdModel): + """Subclass of AvdModel.""" + + class DynamicItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "access_list": {"type": str}, + "comment": {"type": str}, + "nat_type": {"type": str}, + "pool_name": {"type": str}, + "priority": {"type": int}, + "_custom_data": {"type": dict}, + } + access_list: str + comment: str | None + nat_type: Literal["overload", "pool", "pool-address-only", "pool-full-cone"] + pool_name: str | None + """ + required if 'nat_type' is pool, pool-address-only or pool-full-cone. + ignored if 'nat_type' is + overload. + """ + priority: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + access_list: str | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + nat_type: Literal["overload", "pool", "pool-address-only", "pool-full-cone"] | UndefinedType = Undefined, + pool_name: str | None | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DynamicItem. + + + Subclass of AvdModel. + + Args: + access_list: access_list + comment: comment + nat_type: nat_type + pool_name: + required if 'nat_type' is pool, pool-address-only or pool-full-cone. + ignored if 'nat_type' is + overload. + priority: priority + _custom_data: _custom_data + + """ + + class Dynamic(AvdIndexedList[str, DynamicItem]): + """Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`).""" + + _primary_key: ClassVar[str] = "access_list" + + Dynamic._item_type = DynamicItem + + class StaticItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "access_list": {"type": str}, + "comment": {"type": str}, + "direction": {"type": str}, + "group": {"type": int}, + "original_ip": {"type": str}, + "original_port": {"type": int}, + "priority": {"type": int}, + "protocol": {"type": str}, + "translated_ip": {"type": str}, + "translated_port": {"type": int}, + "_custom_data": {"type": dict}, + } + access_list: str | None + """'access_list' and 'group' are mutual exclusive.""" + comment: str | None + direction: Literal["egress", "ingress"] | None + """ + Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware + platform. + EOS might remove this keyword in the configuration. So, check the configuration on + targeted HW/SW. + """ + group: int | None + """'access_list' and 'group' are mutual exclusive.""" + original_ip: str | None + """IPv4 address. The combination of `original_ip` and `original_port` must be unique.""" + original_port: int | None + """TCP/UDP port. The combination of `original_ip` and `original_port` must be unique.""" + priority: int | None + protocol: Literal["udp", "tcp"] | None + translated_ip: str + """IPv4 address.""" + translated_port: int | None + """requires 'original_port'.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + access_list: str | None | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + direction: Literal["egress", "ingress"] | None | UndefinedType = Undefined, + group: int | None | UndefinedType = Undefined, + original_ip: str | None | UndefinedType = Undefined, + original_port: int | None | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + protocol: Literal["udp", "tcp"] | None | UndefinedType = Undefined, + translated_ip: str | UndefinedType = Undefined, + translated_port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StaticItem. + + + Subclass of AvdModel. + + Args: + access_list: 'access_list' and 'group' are mutual exclusive. + comment: comment + direction: + Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware + platform. + EOS might remove this keyword in the configuration. So, check the configuration on + targeted HW/SW. + group: 'access_list' and 'group' are mutual exclusive. + original_ip: IPv4 address. The combination of `original_ip` and `original_port` must be unique. + original_port: TCP/UDP port. The combination of `original_ip` and `original_port` must be unique. + priority: priority + protocol: protocol + translated_ip: IPv4 address. + translated_port: requires 'original_port'. + _custom_data: _custom_data + + """ + + class Static(AvdList[StaticItem]): + """Subclass of AvdList with `StaticItem` items.""" + + Static._item_type = StaticItem + + _fields: ClassVar[dict] = {"dynamic": {"type": Dynamic}, "static": {"type": Static}, "_custom_data": {"type": dict}} + dynamic: Dynamic + """Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`).""" + static: Static + """Subclass of AvdList with `StaticItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dynamic: Dynamic | UndefinedType = Undefined, + static: Static | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Source. + + + Subclass of AvdModel. + + Args: + dynamic: Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`). + static: Subclass of AvdList with `StaticItem` items. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "service_profile": {"type": str}, + "destination": {"type": Destination}, + "source": {"type": Source}, + "_custom_data": {"type": dict}, + } + service_profile: str | None + """NAT interface profile.""" + destination: Destination + """Subclass of AvdModel.""" + source: Source + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + service_profile: str | None | UndefinedType = Undefined, + destination: Destination | UndefinedType = Undefined, + source: Source | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpNat. + + + Subclass of AvdModel. + + Args: + service_profile: NAT interface profile. + destination: Subclass of AvdModel. + source: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Ipv6NdPrefixesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "ipv6_prefix": {"type": str}, + "valid_lifetime": {"type": str}, + "preferred_lifetime": {"type": str}, + "no_autoconfig_flag": {"type": bool}, + "_custom_data": {"type": dict}, + } + ipv6_prefix: str + valid_lifetime: str | None + """Infinite or lifetime in seconds.""" + preferred_lifetime: str | None + """Infinite or lifetime in seconds.""" + no_autoconfig_flag: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv6_prefix: str | UndefinedType = Undefined, + valid_lifetime: str | None | UndefinedType = Undefined, + preferred_lifetime: str | None | UndefinedType = Undefined, + no_autoconfig_flag: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6NdPrefixesItem. + + + Subclass of AvdModel. + + Args: + ipv6_prefix: ipv6_prefix + valid_lifetime: Infinite or lifetime in seconds. + preferred_lifetime: Infinite or lifetime in seconds. + no_autoconfig_flag: no_autoconfig_flag + _custom_data: _custom_data + + """ + + class Ipv6NdPrefixes(AvdIndexedList[str, Ipv6NdPrefixesItem]): + """Subclass of AvdIndexedList with `Ipv6NdPrefixesItem` items. Primary key is `ipv6_prefix` (`str`).""" + + _primary_key: ClassVar[str] = "ipv6_prefix" + + Ipv6NdPrefixes._item_type = Ipv6NdPrefixesItem + + class Ipv6DhcpRelayDestinationsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "address": {"type": str}, + "vrf": {"type": str}, + "local_interface": {"type": str}, + "source_address": {"type": str}, + "link_address": {"type": str}, + "_custom_data": {"type": dict}, + } + address: str + """DHCP server's IPv6 address.""" + vrf: str | None + local_interface: str | None + """Local interface to communicate with DHCP server - mutually exclusive to source_address.""" + source_address: str | None + """Source IPv6 address to communicate with DHCP server - mutually exclusive to local_interface.""" + link_address: str | None + """Override the default link address specified in the relayed DHCP packet.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + address: str | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + local_interface: str | None | UndefinedType = Undefined, + source_address: str | None | UndefinedType = Undefined, + link_address: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6DhcpRelayDestinationsItem. + + + Subclass of AvdModel. + + Args: + address: DHCP server's IPv6 address. + vrf: vrf + local_interface: Local interface to communicate with DHCP server - mutually exclusive to source_address. + source_address: Source IPv6 address to communicate with DHCP server - mutually exclusive to local_interface. + link_address: Override the default link address specified in the relayed DHCP packet. + _custom_data: _custom_data + + """ + + class Ipv6DhcpRelayDestinations(AvdIndexedList[str, Ipv6DhcpRelayDestinationsItem]): + """ + Subclass of AvdIndexedList with `Ipv6DhcpRelayDestinationsItem` items. Primary key is `address` + (`str`). + """ + + _primary_key: ClassVar[str] = "address" + + Ipv6DhcpRelayDestinations._item_type = Ipv6DhcpRelayDestinationsItem + + class Multicast(AvdModel): + """Subclass of AvdModel.""" + + class Ipv4(AvdModel): + """Subclass of AvdModel.""" + + class BoundariesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"boundary": {"type": str}, "out": {"type": bool}, "_custom_data": {"type": dict}} + boundary: str | None + """ACL name or multicast IP subnet.""" + out: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + boundary: str | None | UndefinedType = Undefined, + out: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BoundariesItem. + + + Subclass of AvdModel. + + Args: + boundary: ACL name or multicast IP subnet. + out: out + _custom_data: _custom_data + + """ + + class Boundaries(AvdList[BoundariesItem]): + """Subclass of AvdList with `BoundariesItem` items.""" + + Boundaries._item_type = BoundariesItem + + _fields: ClassVar[dict] = {"boundaries": {"type": Boundaries}, "static": {"type": bool}, "_custom_data": {"type": dict}} + boundaries: Boundaries + """Subclass of AvdList with `BoundariesItem` items.""" + static: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + boundaries: Boundaries | UndefinedType = Undefined, + static: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4. + + + Subclass of AvdModel. + + Args: + boundaries: Subclass of AvdList with `BoundariesItem` items. + static: static + _custom_data: _custom_data + + """ + + class Ipv6(AvdModel): + """Subclass of AvdModel.""" + + class BoundariesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"boundary": {"type": str}, "_custom_data": {"type": dict}} + boundary: str | None + """ACL name or multicast IP subnet.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, boundary: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + BoundariesItem. + + + Subclass of AvdModel. + + Args: + boundary: ACL name or multicast IP subnet. + _custom_data: _custom_data + + """ + + class Boundaries(AvdList[BoundariesItem]): + """Subclass of AvdList with `BoundariesItem` items.""" + + Boundaries._item_type = BoundariesItem + + _fields: ClassVar[dict] = {"boundaries": {"type": Boundaries}, "static": {"type": bool}, "_custom_data": {"type": dict}} + boundaries: Boundaries + """Subclass of AvdList with `BoundariesItem` items.""" + static: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + boundaries: Boundaries | UndefinedType = Undefined, + static: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6. + + + Subclass of AvdModel. + + Args: + boundaries: Subclass of AvdList with `BoundariesItem` items. + static: static + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ipv4": {"type": Ipv4}, "ipv6": {"type": Ipv6}, "_custom_data": {"type": dict}} + ipv4: Ipv4 + """Subclass of AvdModel.""" + ipv6: Ipv6 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4: Ipv4 | UndefinedType = Undefined, + ipv6: Ipv6 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Multicast. + + + Subclass of AvdModel. + + Args: + ipv4: Subclass of AvdModel. + ipv6: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class OspfMessageDigestKeysItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"id": {"type": int}, "hash_algorithm": {"type": str}, "key": {"type": str}, "_custom_data": {"type": dict}} + id: int + hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None + key: str | None + """Encrypted password - only type 7 supported.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + OspfMessageDigestKeysItem. + + + Subclass of AvdModel. + + Args: + id: id + hash_algorithm: hash_algorithm + key: Encrypted password - only type 7 supported. + _custom_data: _custom_data + + """ + + class OspfMessageDigestKeys(AvdIndexedList[int, OspfMessageDigestKeysItem]): + """Subclass of AvdIndexedList with `OspfMessageDigestKeysItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + OspfMessageDigestKeys._item_type = OspfMessageDigestKeysItem + + class Pim(AvdModel): + """Subclass of AvdModel.""" + + class Ipv4(AvdModel): + """Subclass of AvdModel.""" + + class Hello(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"count": {"type": str}, "interval": {"type": int}, "_custom_data": {"type": dict}} + count: str | None + """Number of missed hellos after which the neighbor expires. Range <1.5-65535>.""" + interval: int | None + """PIM hello interval in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + count: str | None | UndefinedType = Undefined, + interval: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Hello. + + + Subclass of AvdModel. + + Args: + count: Number of missed hellos after which the neighbor expires. Range <1.5-65535>. + interval: PIM hello interval in seconds. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "border_router": {"type": bool}, + "dr_priority": {"type": int}, + "sparse_mode": {"type": bool}, + "bfd": {"type": bool}, + "bidirectional": {"type": bool}, + "hello": {"type": Hello}, + "_custom_data": {"type": dict}, + } + border_router: bool | None + """Configure PIM border router. EOS default is false.""" + dr_priority: int | None + sparse_mode: bool | None + bfd: bool | None + """Set the default for whether Bidirectional Forwarding Detection is enabled for PIM.""" + bidirectional: bool | None + hello: Hello + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + border_router: bool | None | UndefinedType = Undefined, + dr_priority: int | None | UndefinedType = Undefined, + sparse_mode: bool | None | UndefinedType = Undefined, + bfd: bool | None | UndefinedType = Undefined, + bidirectional: bool | None | UndefinedType = Undefined, + hello: Hello | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4. + + + Subclass of AvdModel. + + Args: + border_router: Configure PIM border router. EOS default is false. + dr_priority: dr_priority + sparse_mode: sparse_mode + bfd: Set the default for whether Bidirectional Forwarding Detection is enabled for PIM. + bidirectional: bidirectional + hello: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ipv4": {"type": Ipv4}, "_custom_data": {"type": dict}} + ipv4: Ipv4 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, ipv4: Ipv4 | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Pim. + + + Subclass of AvdModel. + + Args: + ipv4: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MacSecurity(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "_custom_data": {"type": dict}} + profile: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, profile: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + MacSecurity. + + + Subclass of AvdModel. + + Args: + profile: profile + _custom_data: _custom_data + + """ + + class TcpMssCeiling(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "ipv4_segment_size": {"type": int}, + "ipv6_segment_size": {"type": int}, + "direction": {"type": str}, + "_custom_data": {"type": dict}, + } + ipv4_segment_size: int | None + ipv6_segment_size: int | None + direction: Literal["egress", "ingress"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4_segment_size: int | None | UndefinedType = Undefined, + ipv6_segment_size: int | None | UndefinedType = Undefined, + direction: Literal["egress", "ingress"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TcpMssCeiling. + + + Subclass of AvdModel. + + Args: + ipv4_segment_size: ipv4_segment_size + ipv6_segment_size: ipv6_segment_size + direction: direction + _custom_data: _custom_data + + """ + + class ChannelGroup(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"id": {"type": int}, "mode": {"type": str}, "_custom_data": {"type": dict}} + id: int | None + mode: Literal["on", "active", "passive"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | None | UndefinedType = Undefined, + mode: Literal["on", "active", "passive"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ChannelGroup. + + + Subclass of AvdModel. + + Args: + id: id + mode: mode + _custom_data: _custom_data + + """ + + class IsisAuthentication(AvdModel): + """Subclass of AvdModel.""" + + class Both(AvdModel): + """Subclass of AvdModel.""" + + class KeyIdsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "algorithm": {"type": str}, + "key_type": {"type": str}, + "key": {"type": str}, + "rfc_5310": {"type": bool}, + "_custom_data": {"type": dict}, + } + id: int + """Configure authentication key-id.""" + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + key_type: Literal["0", "7", "8a"] + """Configure authentication key type.""" + key: str + """Password string.""" + rfc_5310: bool | None + """SHA digest computation according to rfc5310.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + key_type: Literal["0", "7", "8a"] | UndefinedType = Undefined, + key: str | UndefinedType = Undefined, + rfc_5310: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + KeyIdsItem. + + + Subclass of AvdModel. + + Args: + id: Configure authentication key-id. + algorithm: algorithm + key_type: Configure authentication key type. + key: Password string. + rfc_5310: SHA digest computation according to rfc5310. + _custom_data: _custom_data + + """ + + class KeyIds(AvdIndexedList[int, KeyIdsItem]): + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + KeyIds._item_type = KeyIdsItem + + class Sha(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"key_id": {"type": int}, "_custom_data": {"type": dict}} + key_id: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, key_id: int | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Sha. + + + Subclass of AvdModel. + + Args: + key_id: key_id + _custom_data: _custom_data + + """ + + class SharedSecret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "algorithm": {"type": str}, "_custom_data": {"type": dict}} + profile: str + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SharedSecret. + + + Subclass of AvdModel. + + Args: + profile: profile + algorithm: algorithm + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "key_type": {"type": str}, + "key": {"type": str}, + "key_ids": {"type": KeyIds}, + "mode": {"type": str}, + "sha": {"type": Sha}, + "shared_secret": {"type": SharedSecret}, + "rx_disabled": {"type": bool}, + "_custom_data": {"type": dict}, + } + key_type: Literal["0", "7", "8a"] | None + """Configure authentication key type.""" + key: str | None + """Password string. `key_type` is required for this setting.""" + key_ids: KeyIds + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + mode: Literal["md5", "sha", "text", "shared-secret"] | None + """Authentication mode.""" + sha: Sha + """ + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + """ + shared_secret: SharedSecret + """ + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + """ + rx_disabled: bool | None + """Disable authentication check on the receive side.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + key_type: Literal["0", "7", "8a"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + key_ids: KeyIds | UndefinedType = Undefined, + mode: Literal["md5", "sha", "text", "shared-secret"] | None | UndefinedType = Undefined, + sha: Sha | UndefinedType = Undefined, + shared_secret: SharedSecret | UndefinedType = Undefined, + rx_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Both. + + + Subclass of AvdModel. + + Args: + key_type: Configure authentication key type. + key: Password string. `key_type` is required for this setting. + key_ids: Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`). + mode: Authentication mode. + sha: + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + shared_secret: + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + rx_disabled: Disable authentication check on the receive side. + _custom_data: _custom_data + + """ + + class Level1(AvdModel): + """Subclass of AvdModel.""" + + class KeyIdsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "algorithm": {"type": str}, + "key_type": {"type": str}, + "key": {"type": str}, + "rfc_5310": {"type": bool}, + "_custom_data": {"type": dict}, + } + id: int + """Configure authentication key-id.""" + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + key_type: Literal["0", "7", "8a"] + """Configure authentication key type.""" + key: str + """Password string.""" + rfc_5310: bool | None + """SHA digest computation according to rfc5310.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + key_type: Literal["0", "7", "8a"] | UndefinedType = Undefined, + key: str | UndefinedType = Undefined, + rfc_5310: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + KeyIdsItem. + + + Subclass of AvdModel. + + Args: + id: Configure authentication key-id. + algorithm: algorithm + key_type: Configure authentication key type. + key: Password string. + rfc_5310: SHA digest computation according to rfc5310. + _custom_data: _custom_data + + """ + + class KeyIds(AvdIndexedList[int, KeyIdsItem]): + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + KeyIds._item_type = KeyIdsItem + + class Sha(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"key_id": {"type": int}, "_custom_data": {"type": dict}} + key_id: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, key_id: int | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Sha. + + + Subclass of AvdModel. + + Args: + key_id: key_id + _custom_data: _custom_data + + """ + + class SharedSecret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "algorithm": {"type": str}, "_custom_data": {"type": dict}} + profile: str + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SharedSecret. + + + Subclass of AvdModel. + + Args: + profile: profile + algorithm: algorithm + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "key_type": {"type": str}, + "key": {"type": str}, + "key_ids": {"type": KeyIds}, + "mode": {"type": str}, + "sha": {"type": Sha}, + "shared_secret": {"type": SharedSecret}, + "rx_disabled": {"type": bool}, + "_custom_data": {"type": dict}, + } + key_type: Literal["0", "7", "8a"] | None + """Configure authentication key type.""" + key: str | None + """Password string. `key_type` is required for this setting.""" + key_ids: KeyIds + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + mode: Literal["md5", "sha", "text", "shared-secret"] | None + """Authentication mode.""" + sha: Sha + """ + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + """ + shared_secret: SharedSecret + """ + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + """ + rx_disabled: bool | None + """Disable authentication check on the receive side.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + key_type: Literal["0", "7", "8a"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + key_ids: KeyIds | UndefinedType = Undefined, + mode: Literal["md5", "sha", "text", "shared-secret"] | None | UndefinedType = Undefined, + sha: Sha | UndefinedType = Undefined, + shared_secret: SharedSecret | UndefinedType = Undefined, + rx_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Level1. + + + Subclass of AvdModel. + + Args: + key_type: Configure authentication key type. + key: Password string. `key_type` is required for this setting. + key_ids: Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`). + mode: Authentication mode. + sha: + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + shared_secret: + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + rx_disabled: Disable authentication check on the receive side. + _custom_data: _custom_data + + """ + + class Level2(AvdModel): + """Subclass of AvdModel.""" + + class KeyIdsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "algorithm": {"type": str}, + "key_type": {"type": str}, + "key": {"type": str}, + "rfc_5310": {"type": bool}, + "_custom_data": {"type": dict}, + } + id: int + """Configure authentication key-id.""" + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + key_type: Literal["0", "7", "8a"] + """Configure authentication key type.""" + key: str + """Password string.""" + rfc_5310: bool | None + """SHA digest computation according to rfc5310.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + key_type: Literal["0", "7", "8a"] | UndefinedType = Undefined, + key: str | UndefinedType = Undefined, + rfc_5310: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + KeyIdsItem. + + + Subclass of AvdModel. + + Args: + id: Configure authentication key-id. + algorithm: algorithm + key_type: Configure authentication key type. + key: Password string. + rfc_5310: SHA digest computation according to rfc5310. + _custom_data: _custom_data + + """ + + class KeyIds(AvdIndexedList[int, KeyIdsItem]): + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + KeyIds._item_type = KeyIdsItem + + class Sha(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"key_id": {"type": int}, "_custom_data": {"type": dict}} + key_id: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, key_id: int | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Sha. + + + Subclass of AvdModel. + + Args: + key_id: key_id + _custom_data: _custom_data + + """ + + class SharedSecret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "algorithm": {"type": str}, "_custom_data": {"type": dict}} + profile: str + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SharedSecret. + + + Subclass of AvdModel. + + Args: + profile: profile + algorithm: algorithm + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "key_type": {"type": str}, + "key": {"type": str}, + "key_ids": {"type": KeyIds}, + "mode": {"type": str}, + "sha": {"type": Sha}, + "shared_secret": {"type": SharedSecret}, + "rx_disabled": {"type": bool}, + "_custom_data": {"type": dict}, + } + key_type: Literal["0", "7", "8a"] | None + """Configure authentication key type.""" + key: str | None + """Password string. `key_type` is required for this setting.""" + key_ids: KeyIds + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + mode: Literal["md5", "sha", "text", "shared-secret"] | None + """Authentication mode.""" + sha: Sha + """ + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + """ + shared_secret: SharedSecret + """ + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + """ + rx_disabled: bool | None + """Disable authentication check on the receive side.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + key_type: Literal["0", "7", "8a"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + key_ids: KeyIds | UndefinedType = Undefined, + mode: Literal["md5", "sha", "text", "shared-secret"] | None | UndefinedType = Undefined, + sha: Sha | UndefinedType = Undefined, + shared_secret: SharedSecret | UndefinedType = Undefined, + rx_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Level2. + + + Subclass of AvdModel. + + Args: + key_type: Configure authentication key type. + key: Password string. `key_type` is required for this setting. + key_ids: Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`). + mode: Authentication mode. + sha: + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + shared_secret: + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + rx_disabled: Disable authentication check on the receive side. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"both": {"type": Both}, "level_1": {"type": Level1}, "level_2": {"type": Level2}, "_custom_data": {"type": dict}} + both: Both + """ + Authentication settings for level-1 and level-2. 'both' takes precedence over 'level_1' and + 'level_2' settings. + + Subclass of AvdModel. + """ + level_1: Level1 + """ + Authentication settings for level-1. 'both' takes precedence over 'level_1' and 'level_2' settings. + Subclass of AvdModel. + """ + level_2: Level2 + """ + Authentication settings for level-2. 'both' takes precedence over 'level_1' and 'level_2' settings. + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + both: Both | UndefinedType = Undefined, + level_1: Level1 | UndefinedType = Undefined, + level_2: Level2 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IsisAuthentication. + + + Subclass of AvdModel. + + Args: + both: + Authentication settings for level-1 and level-2. 'both' takes precedence over 'level_1' and + 'level_2' settings. + + Subclass of AvdModel. + level_1: + Authentication settings for level-1. 'both' takes precedence over 'level_1' and 'level_2' settings. + Subclass of AvdModel. + level_2: + Authentication settings for level-2. 'both' takes precedence over 'level_1' and 'level_2' settings. + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Poe(AvdModel): + """Subclass of AvdModel.""" + + class Reboot(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"action": {"type": str}, "_custom_data": {"type": dict}} + action: Literal["maintain", "power-off"] | None + """PoE action for interface.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["maintain", "power-off"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Reboot. + + + Subclass of AvdModel. + + Args: + action: PoE action for interface. + _custom_data: _custom_data + + """ + + class LinkDown(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"action": {"type": str}, "power_off_delay": {"type": int}, "_custom_data": {"type": dict}} + action: Literal["maintain", "power-off"] | None + """PoE action for interface.""" + power_off_delay: int | None + """ + Number of seconds to delay shutting the power off after a link down event occurs. Default value is 5 + seconds in EOS. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["maintain", "power-off"] | None | UndefinedType = Undefined, + power_off_delay: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkDown. + + + Subclass of AvdModel. + + Args: + action: PoE action for interface. + power_off_delay: + Number of seconds to delay shutting the power off after a link down event occurs. Default value is 5 + seconds in EOS. + _custom_data: _custom_data + + """ + + class Shutdown(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"action": {"type": str}, "_custom_data": {"type": dict}} + action: Literal["maintain", "power-off"] | None + """PoE action for interface.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["maintain", "power-off"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Shutdown. + + + Subclass of AvdModel. + + Args: + action: PoE action for interface. + _custom_data: _custom_data + + """ + + class Limit(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"field_class": {"type": int}, "watts": {"type": str}, "fixed": {"type": bool}, "_custom_data": {"type": dict}} + _field_to_key_map: ClassVar[dict] = {"field_class": "class"} + _key_to_field_map: ClassVar[dict] = {"class": "field_class"} + field_class: int | None + watts: str | None + fixed: bool | None + """Set to ignore hardware classification.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + field_class: int | None | UndefinedType = Undefined, + watts: str | None | UndefinedType = Undefined, + fixed: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Limit. + + + Subclass of AvdModel. + + Args: + field_class: field_class + watts: watts + fixed: Set to ignore hardware classification. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "disabled": {"type": bool, "default": False}, + "priority": {"type": str}, + "reboot": {"type": Reboot}, + "link_down": {"type": LinkDown}, + "shutdown": {"type": Shutdown}, + "limit": {"type": Limit}, + "negotiation_lldp": {"type": bool}, + "legacy_detect": {"type": bool}, + "_custom_data": {"type": dict}, + } + disabled: bool + """ + Disable PoE on a POE capable port. PoE is enabled on all ports that support it by default in EOS. + + Default value: `False` + """ + priority: Literal["critical", "high", "medium", "low"] | None + """Prioritize a port's power in the event that one of the switch's power supplies loses power.""" + reboot: Reboot + """ + Set the PoE power behavior for a PoE port when the system is rebooted. + + Subclass of AvdModel. + """ + link_down: LinkDown + """ + Set the PoE power behavior for a PoE port when the port goes down. + + Subclass of AvdModel. + """ + shutdown: Shutdown + """ + Set the PoE power behavior for a PoE port when the port is admin down. + + Subclass of AvdModel. + """ + limit: Limit + """ + Override the hardware-negotiated power limit using either wattage or a power class. Note that if + using a power class, AVD will automatically convert the class value to the wattage value + corresponding to that power class. + + Subclass of AvdModel. + """ + negotiation_lldp: bool | None + """ + Disable to prevent port from negotiating power with powered devices over LLDP. Enabled by default in + EOS. + """ + legacy_detect: bool | None + """ + Allow a subset of legacy devices to work with the PoE switch. Disabled by default in EOS because it + can cause false positive detections. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + disabled: bool | UndefinedType = Undefined, + priority: Literal["critical", "high", "medium", "low"] | None | UndefinedType = Undefined, + reboot: Reboot | UndefinedType = Undefined, + link_down: LinkDown | UndefinedType = Undefined, + shutdown: Shutdown | UndefinedType = Undefined, + limit: Limit | UndefinedType = Undefined, + negotiation_lldp: bool | None | UndefinedType = Undefined, + legacy_detect: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Poe. + + + Subclass of AvdModel. + + Args: + disabled: Disable PoE on a POE capable port. PoE is enabled on all ports that support it by default in EOS. + priority: Prioritize a port's power in the event that one of the switch's power supplies loses power. + reboot: + Set the PoE power behavior for a PoE port when the system is rebooted. + + Subclass of AvdModel. + link_down: + Set the PoE power behavior for a PoE port when the port goes down. + + Subclass of AvdModel. + shutdown: + Set the PoE power behavior for a PoE port when the port is admin down. + + Subclass of AvdModel. + limit: + Override the hardware-negotiated power limit using either wattage or a power class. Note that if + using a power class, AVD will automatically convert the class value to the wattage value + corresponding to that power class. + + Subclass of AvdModel. + negotiation_lldp: + Disable to prevent port from negotiating power with powered devices over LLDP. Enabled by default in + EOS. + legacy_detect: + Allow a subset of legacy devices to work with the PoE switch. Disabled by default in EOS because it + can cause false positive detections. + _custom_data: _custom_data + + """ + + class Ptp(AvdModel): + """Subclass of AvdModel.""" + + class Announce(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interval": {"type": int}, "timeout": {"type": int}, "_custom_data": {"type": dict}} + interval: int | None + timeout: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | None | UndefinedType = Undefined, + timeout: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Announce. + + + Subclass of AvdModel. + + Args: + interval: interval + timeout: timeout + _custom_data: _custom_data + + """ + + class Profile(AvdModel): + """Subclass of AvdModel.""" + + class G82751(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"destination_mac_address": {"type": str}, "_custom_data": {"type": dict}} + destination_mac_address: Literal["forwardable", "non-forwardable"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + destination_mac_address: Literal["forwardable", "non-forwardable"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + G82751. + + + Subclass of AvdModel. + + Args: + destination_mac_address: destination_mac_address + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"g8275_1": {"type": G82751}, "_custom_data": {"type": dict}} + g8275_1: G82751 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, g8275_1: G82751 | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Profile. + + + Subclass of AvdModel. + + Args: + g8275_1: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class SyncMessage(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interval": {"type": int}, "_custom_data": {"type": dict}} + interval: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, interval: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + SyncMessage. + + + Subclass of AvdModel. + + Args: + interval: interval + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enable": {"type": bool}, + "announce": {"type": Announce}, + "delay_req": {"type": int}, + "delay_mechanism": {"type": str}, + "profile": {"type": Profile}, + "sync_message": {"type": SyncMessage}, + "role": {"type": str}, + "vlan": {"type": str}, + "transport": {"type": str}, + "_custom_data": {"type": dict}, + } + enable: bool | None + announce: Announce + """Subclass of AvdModel.""" + delay_req: int | None + delay_mechanism: Literal["e2e", "p2p"] | None + profile: Profile + """Subclass of AvdModel.""" + sync_message: SyncMessage + """Subclass of AvdModel.""" + role: Literal["master", "dynamic"] | None + vlan: str | None + """VLAN can be 'all' or list of vlans as string.""" + transport: Literal["ipv4", "ipv6", "layer2"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enable: bool | None | UndefinedType = Undefined, + announce: Announce | UndefinedType = Undefined, + delay_req: int | None | UndefinedType = Undefined, + delay_mechanism: Literal["e2e", "p2p"] | None | UndefinedType = Undefined, + profile: Profile | UndefinedType = Undefined, + sync_message: SyncMessage | UndefinedType = Undefined, + role: Literal["master", "dynamic"] | None | UndefinedType = Undefined, + vlan: str | None | UndefinedType = Undefined, + transport: Literal["ipv4", "ipv6", "layer2"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ptp. + + + Subclass of AvdModel. + + Args: + enable: enable + announce: Subclass of AvdModel. + delay_req: delay_req + delay_mechanism: delay_mechanism + profile: Subclass of AvdModel. + sync_message: Subclass of AvdModel. + role: role + vlan: VLAN can be 'all' or list of vlans as string. + transport: transport + _custom_data: _custom_data + + """ + + class StormControl(AvdModel): + """Subclass of AvdModel.""" + + class All(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional field and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + All. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional field and is hardware dependent. + _custom_data: _custom_data + + """ + + class Broadcast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional field and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Broadcast. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional field and is hardware dependent. + _custom_data: _custom_data + + """ + + class Multicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional field and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Multicast. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional field and is hardware dependent. + _custom_data: _custom_data + + """ + + class UnknownUnicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional field and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + UnknownUnicast. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional field and is hardware dependent. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "all": {"type": All}, + "broadcast": {"type": Broadcast}, + "multicast": {"type": Multicast}, + "unknown_unicast": {"type": UnknownUnicast}, + "_custom_data": {"type": dict}, + } + all: All + """Subclass of AvdModel.""" + broadcast: Broadcast + """Subclass of AvdModel.""" + multicast: Multicast + """Subclass of AvdModel.""" + unknown_unicast: UnknownUnicast + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + all: All | UndefinedType = Undefined, + broadcast: Broadcast | UndefinedType = Undefined, + multicast: Multicast | UndefinedType = Undefined, + unknown_unicast: UnknownUnicast | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StormControl. + + + Subclass of AvdModel. + + Args: + all: Subclass of AvdModel. + broadcast: Subclass of AvdModel. + multicast: Subclass of AvdModel. + unknown_unicast: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Logging(AvdModel): + """Subclass of AvdModel.""" + + class Event(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "link_status": {"type": bool}, + "congestion_drops": {"type": bool}, + "spanning_tree": {"type": bool}, + "storm_control_discards": {"type": bool}, + "_custom_data": {"type": dict}, + } + link_status: bool | None + congestion_drops: bool | None + spanning_tree: bool | None + storm_control_discards: bool | None + """Discards due to storm-control.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + link_status: bool | None | UndefinedType = Undefined, + congestion_drops: bool | None | UndefinedType = Undefined, + spanning_tree: bool | None | UndefinedType = Undefined, + storm_control_discards: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Event. + + + Subclass of AvdModel. + + Args: + link_status: link_status + congestion_drops: congestion_drops + spanning_tree: spanning_tree + storm_control_discards: Discards due to storm-control. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"event": {"type": Event}, "_custom_data": {"type": dict}} + event: Event + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, event: Event | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Logging. + + + Subclass of AvdModel. + + Args: + event: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Lldp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"transmit": {"type": bool}, "receive": {"type": bool}, "ztp_vlan": {"type": int}, "_custom_data": {"type": dict}} + transmit: bool | None + receive: bool | None + ztp_vlan: int | None + """ZTP vlan number.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + transmit: bool | None | UndefinedType = Undefined, + receive: bool | None | UndefinedType = Undefined, + ztp_vlan: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Lldp. + + + Subclass of AvdModel. + + Args: + transmit: transmit + receive: receive + ztp_vlan: ZTP vlan number. + _custom_data: _custom_data + + """ + + class VlanTranslationsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "field_from": {"type": str}, + "to": {"type": int}, + "direction": {"type": str, "default": "both"}, + "_custom_data": {"type": dict}, + } + _field_to_key_map: ClassVar[dict] = {"field_from": "from"} + _key_to_field_map: ClassVar[dict] = {"from": "field_from"} + field_from: str | None + """List of vlans as string (only one vlan if direction is "both").""" + to: int | None + """VLAN ID.""" + direction: Literal["in", "out", "both"] + """Default value: `"both"`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + field_from: str | None | UndefinedType = Undefined, + to: int | None | UndefinedType = Undefined, + direction: Literal["in", "out", "both"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VlanTranslationsItem. + + + Subclass of AvdModel. + + Args: + field_from: List of vlans as string (only one vlan if direction is "both"). + to: VLAN ID. + direction: direction + _custom_data: _custom_data + + """ + + class VlanTranslations(AvdList[VlanTranslationsItem]): + """Subclass of AvdList with `VlanTranslationsItem` items.""" + + VlanTranslations._item_type = VlanTranslationsItem + + class Dot1x(AvdModel): + """Subclass of AvdModel.""" + + class Pae(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"mode": {"type": str}, "_custom_data": {"type": dict}} + mode: Literal["authenticator"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, mode: Literal["authenticator"] | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Pae. + + + Subclass of AvdModel. + + Args: + mode: mode + _custom_data: _custom_data + + """ + + class AuthenticationFailure(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"action": {"type": str}, "allow_vlan": {"type": int}, "_custom_data": {"type": dict}} + action: Literal["allow", "drop"] | None + allow_vlan: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["allow", "drop"] | None | UndefinedType = Undefined, + allow_vlan: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AuthenticationFailure. + + + Subclass of AvdModel. + + Args: + action: action + allow_vlan: allow_vlan + _custom_data: _custom_data + + """ + + class HostMode(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"mode": {"type": str}, "multi_host_authenticated": {"type": bool}, "_custom_data": {"type": dict}} + mode: Literal["multi-host", "single-host"] | None + multi_host_authenticated: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["multi-host", "single-host"] | None | UndefinedType = Undefined, + multi_host_authenticated: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + HostMode. + + + Subclass of AvdModel. + + Args: + mode: mode + multi_host_authenticated: multi_host_authenticated + _custom_data: _custom_data + + """ + + class MacBasedAuthentication(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "always": {"type": bool}, + "host_mode_common": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + always: bool | None + host_mode_common: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + always: bool | None | UndefinedType = Undefined, + host_mode_common: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MacBasedAuthentication. + + + Subclass of AvdModel. + + Args: + enabled: enabled + always: always + host_mode_common: host_mode_common + _custom_data: _custom_data + + """ + + class Timeout(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "idle_host": {"type": int}, + "quiet_period": {"type": int}, + "reauth_period": {"type": str}, + "reauth_timeout_ignore": {"type": bool}, + "tx_period": {"type": int}, + "_custom_data": {"type": dict}, + } + idle_host: int | None + quiet_period: int | None + reauth_period: str | None + """Value can be 60-4294967295 or 'server'.""" + reauth_timeout_ignore: bool | None + tx_period: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + idle_host: int | None | UndefinedType = Undefined, + quiet_period: int | None | UndefinedType = Undefined, + reauth_period: str | None | UndefinedType = Undefined, + reauth_timeout_ignore: bool | None | UndefinedType = Undefined, + tx_period: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Timeout. + + + Subclass of AvdModel. + + Args: + idle_host: idle_host + quiet_period: quiet_period + reauth_period: Value can be 60-4294967295 or 'server'. + reauth_timeout_ignore: reauth_timeout_ignore + tx_period: tx_period + _custom_data: _custom_data + + """ + + class Unauthorized(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "access_vlan_membership_egress": {"type": bool}, + "native_vlan_membership_egress": {"type": bool}, + "_custom_data": {"type": dict}, + } + access_vlan_membership_egress: bool | None + native_vlan_membership_egress: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + access_vlan_membership_egress: bool | None | UndefinedType = Undefined, + native_vlan_membership_egress: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Unauthorized. + + + Subclass of AvdModel. + + Args: + access_vlan_membership_egress: access_vlan_membership_egress + native_vlan_membership_egress: native_vlan_membership_egress + _custom_data: _custom_data + + """ + + class Eapol(AvdModel): + """Subclass of AvdModel.""" + + class AuthenticationFailureFallbackMba(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "timeout": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool | None + timeout: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + timeout: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AuthenticationFailureFallbackMba. + + + Subclass of AvdModel. + + Args: + enabled: enabled + timeout: timeout + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "disabled": {"type": bool}, + "authentication_failure_fallback_mba": {"type": AuthenticationFailureFallbackMba}, + "_custom_data": {"type": dict}, + } + disabled: bool | None + authentication_failure_fallback_mba: AuthenticationFailureFallbackMba + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + disabled: bool | None | UndefinedType = Undefined, + authentication_failure_fallback_mba: AuthenticationFailureFallbackMba | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Eapol. + + + Subclass of AvdModel. + + Args: + disabled: disabled + authentication_failure_fallback_mba: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Aaa(AvdModel): + """Subclass of AvdModel.""" + + class Unresponsive(AvdModel): + """Subclass of AvdModel.""" + + class Action(AvdModel): + """Subclass of AvdModel.""" + + class CachedResultsTimeout(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"time_duration": {"type": int}, "time_duration_unit": {"type": str}, "_custom_data": {"type": dict}} + time_duration: int | None + """ + Enable caching for a specific duration - + <1-10000> duration in days + <1-14400000> duration in + minutes + <1-240000> duration in hours + <1-864000000> duration in seconds + """ + time_duration_unit: Literal["days", "hours", "minutes", "seconds"] + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + time_duration: int | None | UndefinedType = Undefined, + time_duration_unit: Literal["days", "hours", "minutes", "seconds"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CachedResultsTimeout. + + + Subclass of AvdModel. + + Args: + time_duration: + Enable caching for a specific duration - + <1-10000> duration in days + <1-14400000> duration in + minutes + <1-240000> duration in hours + <1-864000000> duration in seconds + time_duration_unit: time_duration_unit + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "traffic_allow_access_list": {"type": str}, + "apply_cached_results": {"type": bool}, + "cached_results_timeout": {"type": CachedResultsTimeout}, + "apply_alternate": {"type": bool}, + "traffic_allow": {"type": bool}, + "traffic_allow_vlan": {"type": int}, + "_custom_data": {"type": dict}, + } + traffic_allow_access_list: str | None + """Name of standard access-list to apply when AAA times out.""" + apply_cached_results: bool | None + """Use results from a previous AAA response.""" + cached_results_timeout: CachedResultsTimeout + """Subclass of AvdModel.""" + apply_alternate: bool | None + """ + Apply alternate action if primary action fails. + eg. aaa unresponsive action apply cached-results + else traffic allow + """ + traffic_allow: bool | None + """Set action for supplicant traffic when AAA times out.""" + traffic_allow_vlan: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + traffic_allow_access_list: str | None | UndefinedType = Undefined, + apply_cached_results: bool | None | UndefinedType = Undefined, + cached_results_timeout: CachedResultsTimeout | UndefinedType = Undefined, + apply_alternate: bool | None | UndefinedType = Undefined, + traffic_allow: bool | None | UndefinedType = Undefined, + traffic_allow_vlan: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Action. + + + Subclass of AvdModel. + + Args: + traffic_allow_access_list: Name of standard access-list to apply when AAA times out. + apply_cached_results: Use results from a previous AAA response. + cached_results_timeout: Subclass of AvdModel. + apply_alternate: + Apply alternate action if primary action fails. + eg. aaa unresponsive action apply cached-results + else traffic allow + traffic_allow: Set action for supplicant traffic when AAA times out. + traffic_allow_vlan: traffic_allow_vlan + _custom_data: _custom_data + + """ + + class PhoneAction(AvdModel): + """Subclass of AvdModel.""" + + class CachedResultsTimeout(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"time_duration": {"type": int}, "time_duration_unit": {"type": str}, "_custom_data": {"type": dict}} + time_duration: int | None + """ + Enable caching for a specific duration - + <1-10000> duration in days + <1-14400000> duration in + minutes + <1-240000> duration in hours + <1-864000000> duration in seconds + """ + time_duration_unit: Literal["days", "hours", "minutes", "seconds"] + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + time_duration: int | None | UndefinedType = Undefined, + time_duration_unit: Literal["days", "hours", "minutes", "seconds"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CachedResultsTimeout. + + + Subclass of AvdModel. + + Args: + time_duration: + Enable caching for a specific duration - + <1-10000> duration in days + <1-14400000> duration in + minutes + <1-240000> duration in hours + <1-864000000> duration in seconds + time_duration_unit: time_duration_unit + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "apply_cached_results": {"type": bool}, + "cached_results_timeout": {"type": CachedResultsTimeout}, + "apply_alternate": {"type": bool}, + "traffic_allow": {"type": bool}, + "_custom_data": {"type": dict}, + } + apply_cached_results: bool | None + """Use results from a previous AAA response.""" + cached_results_timeout: CachedResultsTimeout + """Subclass of AvdModel.""" + apply_alternate: bool | None + """ + Apply alternate action if primary action fails. + eg. aaa unresponsive phone action apply cached- + results else traffic allow + """ + traffic_allow: bool | None + """Set action for supplicant traffic when AAA times out.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + apply_cached_results: bool | None | UndefinedType = Undefined, + cached_results_timeout: CachedResultsTimeout | UndefinedType = Undefined, + apply_alternate: bool | None | UndefinedType = Undefined, + traffic_allow: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PhoneAction. + + + Subclass of AvdModel. + + Args: + apply_cached_results: Use results from a previous AAA response. + cached_results_timeout: Subclass of AvdModel. + apply_alternate: + Apply alternate action if primary action fails. + eg. aaa unresponsive phone action apply cached- + results else traffic allow + traffic_allow: Set action for supplicant traffic when AAA times out. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "eap_response": {"type": str}, + "action": {"type": Action}, + "phone_action": {"type": PhoneAction}, + "_custom_data": {"type": dict}, + } + eap_response: Literal["success", "disabled"] | None + """EAP response to send. EOS default is `success`.""" + action: Action + """ + Set action for supplicant when AAA times out. + + Subclass of AvdModel. + """ + phone_action: PhoneAction + """ + Set action for supplicant when AAA times out. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + eap_response: Literal["success", "disabled"] | None | UndefinedType = Undefined, + action: Action | UndefinedType = Undefined, + phone_action: PhoneAction | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Unresponsive. + + + Subclass of AvdModel. + + Args: + eap_response: EAP response to send. EOS default is `success`. + action: + Set action for supplicant when AAA times out. + + Subclass of AvdModel. + phone_action: + Set action for supplicant when AAA times out. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"unresponsive": {"type": Unresponsive}, "_custom_data": {"type": dict}} + unresponsive: Unresponsive + """ + Configure AAA timeout options. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, unresponsive: Unresponsive | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Aaa. + + + Subclass of AvdModel. + + Args: + unresponsive: + Configure AAA timeout options. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "port_control": {"type": str}, + "port_control_force_authorized_phone": {"type": bool}, + "reauthentication": {"type": bool}, + "pae": {"type": Pae}, + "authentication_failure": {"type": AuthenticationFailure}, + "host_mode": {"type": HostMode}, + "mac_based_authentication": {"type": MacBasedAuthentication}, + "mac_based_access_list": {"type": bool}, + "timeout": {"type": Timeout}, + "reauthorization_request_limit": {"type": int}, + "unauthorized": {"type": Unauthorized}, + "eapol": {"type": Eapol}, + "aaa": {"type": Aaa}, + "_custom_data": {"type": dict}, + } + port_control: Literal["auto", "force-authorized", "force-unauthorized"] | None + port_control_force_authorized_phone: bool | None + reauthentication: bool | None + pae: Pae + """Subclass of AvdModel.""" + authentication_failure: AuthenticationFailure + """Subclass of AvdModel.""" + host_mode: HostMode + """Subclass of AvdModel.""" + mac_based_authentication: MacBasedAuthentication + """Subclass of AvdModel.""" + mac_based_access_list: bool | None + """Operate interface in per-mac access-list mode.""" + timeout: Timeout + """Subclass of AvdModel.""" + reauthorization_request_limit: int | None + unauthorized: Unauthorized + """Subclass of AvdModel.""" + eapol: Eapol + """Subclass of AvdModel.""" + aaa: Aaa + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + port_control: Literal["auto", "force-authorized", "force-unauthorized"] | None | UndefinedType = Undefined, + port_control_force_authorized_phone: bool | None | UndefinedType = Undefined, + reauthentication: bool | None | UndefinedType = Undefined, + pae: Pae | UndefinedType = Undefined, + authentication_failure: AuthenticationFailure | UndefinedType = Undefined, + host_mode: HostMode | UndefinedType = Undefined, + mac_based_authentication: MacBasedAuthentication | UndefinedType = Undefined, + mac_based_access_list: bool | None | UndefinedType = Undefined, + timeout: Timeout | UndefinedType = Undefined, + reauthorization_request_limit: int | None | UndefinedType = Undefined, + unauthorized: Unauthorized | UndefinedType = Undefined, + eapol: Eapol | UndefinedType = Undefined, + aaa: Aaa | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dot1x. + + + Subclass of AvdModel. + + Args: + port_control: port_control + port_control_force_authorized_phone: port_control_force_authorized_phone + reauthentication: reauthentication + pae: Subclass of AvdModel. + authentication_failure: Subclass of AvdModel. + host_mode: Subclass of AvdModel. + mac_based_authentication: Subclass of AvdModel. + mac_based_access_list: Operate interface in per-mac access-list mode. + timeout: Subclass of AvdModel. + reauthorization_request_limit: reauthorization_request_limit + unauthorized: Subclass of AvdModel. + eapol: Subclass of AvdModel. + aaa: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Shape(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"rate": {"type": str}, "_custom_data": {"type": dict}} + rate: str | None + """ + Rate in kbps, pps or percent. + Supported options are platform dependent. + Examples: + - "5000 kbps" + - + "1000 pps" + - "20 percent" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, rate: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Shape. + + + Subclass of AvdModel. + + Args: + rate: + Rate in kbps, pps or percent. + Supported options are platform dependent. + Examples: # fmt: skip + - "5000 kbps" + - + "1000 pps" + - "20 percent" + _custom_data: _custom_data + + """ + + class Qos(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"trust": {"type": str}, "dscp": {"type": int}, "cos": {"type": int}, "_custom_data": {"type": dict}} + trust: Literal["dscp", "cos", "disabled"] | None + dscp: int | None + """DSCP value.""" + cos: int | None + """COS value.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + trust: Literal["dscp", "cos", "disabled"] | None | UndefinedType = Undefined, + dscp: int | None | UndefinedType = Undefined, + cos: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Qos. + + + Subclass of AvdModel. + + Args: + trust: trust + dscp: DSCP value. + cos: COS value. + _custom_data: _custom_data + + """ + + class PriorityFlowControl(AvdModel): + """Subclass of AvdModel.""" + + class PrioritiesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"priority": {"type": int}, "no_drop": {"type": bool}, "_custom_data": {"type": dict}} + priority: int + no_drop: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + priority: int | UndefinedType = Undefined, + no_drop: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PrioritiesItem. + + + Subclass of AvdModel. + + Args: + priority: priority + no_drop: no_drop + _custom_data: _custom_data + + """ + + class Priorities(AvdIndexedList[int, PrioritiesItem]): + """Subclass of AvdIndexedList with `PrioritiesItem` items. Primary key is `priority` (`int`).""" + + _primary_key: ClassVar[str] = "priority" + + Priorities._item_type = PrioritiesItem + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "priorities": {"type": Priorities}, "_custom_data": {"type": dict}} + enabled: bool | None + priorities: Priorities + """Subclass of AvdIndexedList with `PrioritiesItem` items. Primary key is `priority` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + priorities: Priorities | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PriorityFlowControl. + + + Subclass of AvdModel. + + Args: + enabled: enabled + priorities: Subclass of AvdIndexedList with `PrioritiesItem` items. Primary key is `priority` (`int`). + _custom_data: _custom_data + + """ + + class Bfd(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "echo": {"type": bool}, + "interval": {"type": int}, + "min_rx": {"type": int}, + "multiplier": {"type": int}, + "_custom_data": {"type": dict}, + } + echo: bool | None + interval: int | None + """Interval in milliseconds.""" + min_rx: int | None + """Rate in milliseconds.""" + multiplier: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + echo: bool | None | UndefinedType = Undefined, + interval: int | None | UndefinedType = Undefined, + min_rx: int | None | UndefinedType = Undefined, + multiplier: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bfd. + + + Subclass of AvdModel. + + Args: + echo: echo + interval: Interval in milliseconds. + min_rx: Rate in milliseconds. + multiplier: multiplier + _custom_data: _custom_data + + """ + + class ServicePolicy(AvdModel): + """Subclass of AvdModel.""" + + class Pbr(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"input": {"type": str}, "_custom_data": {"type": dict}} + input: str | None + """Policy Based Routing Policy-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, input: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Pbr. + + + Subclass of AvdModel. + + Args: + input: Policy Based Routing Policy-map name. + _custom_data: _custom_data + + """ + + class Qos(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"input": {"type": str}, "_custom_data": {"type": dict}} + input: str + """Quality of Service Policy-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, input: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Qos. + + + Subclass of AvdModel. + + Args: + input: Quality of Service Policy-map name. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"pbr": {"type": Pbr}, "qos": {"type": Qos}, "_custom_data": {"type": dict}} + pbr: Pbr + """Subclass of AvdModel.""" + qos: Qos + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + pbr: Pbr | UndefinedType = Undefined, + qos: Qos | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ServicePolicy. + + + Subclass of AvdModel. + + Args: + pbr: Subclass of AvdModel. + qos: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Mpls(AvdModel): + """Subclass of AvdModel.""" + + class Ldp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interface": {"type": bool}, "igp_sync": {"type": bool}, "_custom_data": {"type": dict}} + interface: bool | None + igp_sync: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interface: bool | None | UndefinedType = Undefined, + igp_sync: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ldp. + + + Subclass of AvdModel. + + Args: + interface: interface + igp_sync: igp_sync + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ip": {"type": bool}, "ldp": {"type": Ldp}, "_custom_data": {"type": dict}} + ip: bool | None + ldp: Ldp + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip: bool | None | UndefinedType = Undefined, + ldp: Ldp | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Mpls. + + + Subclass of AvdModel. + + Args: + ip: ip + ldp: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class LacpTimer(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"mode": {"type": str}, "multiplier": {"type": int}, "_custom_data": {"type": dict}} + mode: Literal["fast", "normal"] | None + multiplier: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["fast", "normal"] | None | UndefinedType = Undefined, + multiplier: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LacpTimer. + + + Subclass of AvdModel. + + Args: + mode: mode + multiplier: multiplier + _custom_data: _custom_data + + """ + + class Transceiver(AvdModel): + """Subclass of AvdModel.""" + + class Media(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"override": {"type": str}, "_custom_data": {"type": dict}} + override: str | None + """Transceiver type.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, override: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Media. + + + Subclass of AvdModel. + + Args: + override: Transceiver type. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"frequency": {"type": str}, "frequency_unit": {"type": str}, "media": {"type": Media}, "_custom_data": {"type": dict}} + frequency: str | None + """Transceiver Laser Frequency in GHz (min 190000, max 200000).""" + frequency_unit: Literal["ghz"] | None + """Unit of Transceiver Laser Frequency.""" + media: Media + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + frequency: str | None | UndefinedType = Undefined, + frequency_unit: Literal["ghz"] | None | UndefinedType = Undefined, + media: Media | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Transceiver. + + + Subclass of AvdModel. + + Args: + frequency: Transceiver Laser Frequency in GHz (min 190000, max 200000). + frequency_unit: Unit of Transceiver Laser Frequency. + media: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class TrafficPolicy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"input": {"type": str}, "output": {"type": str}, "_custom_data": {"type": dict}} + input: str | None + """Ingress traffic policy.""" + output: str | None + """Egress traffic policy.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + input: str | None | UndefinedType = Undefined, + output: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TrafficPolicy. + + + Subclass of AvdModel. + + Args: + input: Ingress traffic policy. + output: Egress traffic policy. + _custom_data: _custom_data + + """ + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"session_tracker": {"type": str}, "_custom_data": {"type": dict}} + session_tracker: str | None + """Name of session tracker.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, session_tracker: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + session_tracker: Name of session tracker. + _custom_data: _custom_data + + """ + + class IpIgmpHostProxy(AvdModel): + """Subclass of AvdModel.""" + + class GroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class ExcludeItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"source": {"type": str}, "_custom_data": {"type": dict}} + source: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, source: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + ExcludeItem. + + + Subclass of AvdModel. + + Args: + source: source + _custom_data: _custom_data + + """ + + class Exclude(AvdIndexedList[str, ExcludeItem]): + """Subclass of AvdIndexedList with `ExcludeItem` items. Primary key is `source` (`str`).""" + + _primary_key: ClassVar[str] = "source" + + Exclude._item_type = ExcludeItem + + class IncludeItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"source": {"type": str}, "_custom_data": {"type": dict}} + source: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, source: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + IncludeItem. + + + Subclass of AvdModel. + + Args: + source: source + _custom_data: _custom_data + + """ + + class Include(AvdIndexedList[str, IncludeItem]): + """Subclass of AvdIndexedList with `IncludeItem` items. Primary key is `source` (`str`).""" + + _primary_key: ClassVar[str] = "source" + + Include._item_type = IncludeItem + + _fields: ClassVar[dict] = {"group": {"type": str}, "exclude": {"type": Exclude}, "include": {"type": Include}, "_custom_data": {"type": dict}} + group: str + """Multicast Address.""" + exclude: Exclude + """ + The same source must not be present both in `exclude` and `include` list. + + Subclass of + AvdIndexedList with `ExcludeItem` items. Primary key is `source` (`str`). + """ + include: Include + """ + The same source must not be present both in `exclude` and `include` list. + + Subclass of + AvdIndexedList with `IncludeItem` items. Primary key is `source` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + group: str | UndefinedType = Undefined, + exclude: Exclude | UndefinedType = Undefined, + include: Include | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GroupsItem. + + + Subclass of AvdModel. + + Args: + group: Multicast Address. + exclude: + The same source must not be present both in `exclude` and `include` list. + + Subclass of + AvdIndexedList with `ExcludeItem` items. Primary key is `source` (`str`). + include: + The same source must not be present both in `exclude` and `include` list. + + Subclass of + AvdIndexedList with `IncludeItem` items. Primary key is `source` (`str`). + _custom_data: _custom_data + + """ + + class Groups(AvdIndexedList[str, GroupsItem]): + """Subclass of AvdIndexedList with `GroupsItem` items. Primary key is `group` (`str`).""" + + _primary_key: ClassVar[str] = "group" + + Groups._item_type = GroupsItem + + class AccessListsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "_custom_data": {"type": dict}} + name: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, name: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + AccessListsItem. + + + Subclass of AvdModel. + + Args: + name: name + _custom_data: _custom_data + + """ + + class AccessLists(AvdIndexedList[str, AccessListsItem]): + """Subclass of AvdIndexedList with `AccessListsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + AccessLists._item_type = AccessListsItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "groups": {"type": Groups}, + "report_interval": {"type": int}, + "access_lists": {"type": AccessLists}, + "version": {"type": int}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + groups: Groups + """Subclass of AvdIndexedList with `GroupsItem` items. Primary key is `group` (`str`).""" + report_interval: int | None + """Time interval between unsolicited reports.""" + access_lists: AccessLists + """ + Non-standard Access List name. + + Subclass of AvdIndexedList with `AccessListsItem` items. Primary key + is `name` (`str`). + """ + version: int | None + """IGMP version on IGMP host-proxy interface.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + report_interval: int | None | UndefinedType = Undefined, + access_lists: AccessLists | UndefinedType = Undefined, + version: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpIgmpHostProxy. + + + Subclass of AvdModel. + + Args: + enabled: enabled + groups: Subclass of AvdIndexedList with `GroupsItem` items. Primary key is `group` (`str`). + report_interval: Time interval between unsolicited reports. + access_lists: + Non-standard Access List name. + + Subclass of AvdIndexedList with `AccessListsItem` items. Primary key + is `name` (`str`). + version: IGMP version on IGMP host-proxy interface. + _custom_data: _custom_data + + """ + + class Sflow(AvdModel): + """Subclass of AvdModel.""" + + class Egress(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enable": {"type": bool}, "unmodified_enable": {"type": bool}, "_custom_data": {"type": dict}} + enable: bool | None + unmodified_enable: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enable: bool | None | UndefinedType = Undefined, + unmodified_enable: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Egress. + + + Subclass of AvdModel. + + Args: + enable: enable + unmodified_enable: unmodified_enable + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"enable": {"type": bool}, "egress": {"type": Egress}, "_custom_data": {"type": dict}} + enable: bool | None + egress: Egress + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enable: bool | None | UndefinedType = Undefined, + egress: Egress | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Sflow. + + + Subclass of AvdModel. + + Args: + enable: enable + egress: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class SyncE(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enable": {"type": bool}, "priority": {"type": str}, "_custom_data": {"type": dict}} + enable: bool | None + priority: str | None + """ + The priority is used to influence the reference clock selection. The EOS default priority is 127. + The priority can be configured to any integer between 1-255, or set to `disabled`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enable: bool | None | UndefinedType = Undefined, + priority: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SyncE. + + + Subclass of AvdModel. + + Args: + enable: enable + priority: + The priority is used to influence the reference clock selection. The EOS default priority is 127. + The priority can be configured to any integer between 1-255, or set to `disabled`. + _custom_data: _custom_data + + """ + + class UcTxQueuesItem(AvdModel): + """Subclass of AvdModel.""" + + class RandomDetect(AvdModel): + """Subclass of AvdModel.""" + + class Ecn(AvdModel): + """Subclass of AvdModel.""" + + class Threshold(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "units": {"type": str}, + "min": {"type": int}, + "max": {"type": int}, + "max_probability": {"type": int}, + "weight": {"type": int}, + "_custom_data": {"type": dict}, + } + units: Literal["segments", "bytes", "kbytes", "mbytes", "milliseconds"] + """Indicate the units to be used for the threshold values.""" + min: int + """Set the random-detect ECN minimum-threshold.""" + max: int + """Set the random-detect ECN maximum-threshold.""" + max_probability: int | None + """Set the random-detect ECN max-mark-probability.""" + weight: int | None + """Set the random-detect ECN weight.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + units: Literal["segments", "bytes", "kbytes", "mbytes", "milliseconds"] | UndefinedType = Undefined, + min: int | UndefinedType = Undefined, + max: int | UndefinedType = Undefined, + max_probability: int | None | UndefinedType = Undefined, + weight: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Threshold. + + + Subclass of AvdModel. + + Args: + units: Indicate the units to be used for the threshold values. + min: Set the random-detect ECN minimum-threshold. + max: Set the random-detect ECN maximum-threshold. + max_probability: Set the random-detect ECN max-mark-probability. + weight: Set the random-detect ECN weight. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"count": {"type": bool}, "threshold": {"type": Threshold}, "_custom_data": {"type": dict}} + count: bool | None + """Enable counter for random-detect ECNs.""" + threshold: Threshold + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + count: bool | None | UndefinedType = Undefined, + threshold: Threshold | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ecn. + + + Subclass of AvdModel. + + Args: + count: Enable counter for random-detect ECNs. + threshold: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ecn": {"type": Ecn}, "_custom_data": {"type": dict}} + ecn: Ecn + """ + Explicit Congestion Notification. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, ecn: Ecn | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + RandomDetect. + + + Subclass of AvdModel. + + Args: + ecn: + Explicit Congestion Notification. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"id": {"type": int}, "random_detect": {"type": RandomDetect}, "_custom_data": {"type": dict}} + id: int + """TX-Queue ID.""" + random_detect: RandomDetect + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + random_detect: RandomDetect | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + UcTxQueuesItem. + + + Subclass of AvdModel. + + Args: + id: TX-Queue ID. + random_detect: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class UcTxQueues(AvdIndexedList[int, UcTxQueuesItem]): + """Subclass of AvdIndexedList with `UcTxQueuesItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + UcTxQueues._item_type = UcTxQueuesItem + + class TxQueuesItem(AvdModel): + """Subclass of AvdModel.""" + + class RandomDetect(AvdModel): + """Subclass of AvdModel.""" + + class Ecn(AvdModel): + """Subclass of AvdModel.""" + + class Threshold(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "units": {"type": str}, + "min": {"type": int}, + "max": {"type": int}, + "max_probability": {"type": int}, + "weight": {"type": int}, + "_custom_data": {"type": dict}, + } + units: Literal["segments", "bytes", "kbytes", "mbytes", "milliseconds"] + """Indicate the units to be used for the threshold values.""" + min: int | None + """Set the random-detect ECN minimum-threshold.""" + max: int + """Set the random-detect ECN maximum-threshold.""" + max_probability: int + """Set the random-detect ECN max-mark-probability.""" + weight: int | None + """Set the random-detect ECN weight.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + units: Literal["segments", "bytes", "kbytes", "mbytes", "milliseconds"] | UndefinedType = Undefined, + min: int | None | UndefinedType = Undefined, + max: int | UndefinedType = Undefined, + max_probability: int | UndefinedType = Undefined, + weight: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Threshold. + + + Subclass of AvdModel. + + Args: + units: Indicate the units to be used for the threshold values. + min: Set the random-detect ECN minimum-threshold. + max: Set the random-detect ECN maximum-threshold. + max_probability: Set the random-detect ECN max-mark-probability. + weight: Set the random-detect ECN weight. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"count": {"type": bool}, "threshold": {"type": Threshold}, "_custom_data": {"type": dict}} + count: bool | None + """Enable counter for random-detect ECNs.""" + threshold: Threshold + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + count: bool | None | UndefinedType = Undefined, + threshold: Threshold | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ecn. + + + Subclass of AvdModel. + + Args: + count: Enable counter for random-detect ECNs. + threshold: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ecn": {"type": Ecn}, "_custom_data": {"type": dict}} + ecn: Ecn + """ + Explicit Congestion Notification. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, ecn: Ecn | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + RandomDetect. + + + Subclass of AvdModel. + + Args: + ecn: + Explicit Congestion Notification. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"id": {"type": int}, "random_detect": {"type": RandomDetect}, "_custom_data": {"type": dict}} + id: int + """TX-Queue ID.""" + random_detect: RandomDetect + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + random_detect: RandomDetect | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TxQueuesItem. + + + Subclass of AvdModel. + + Args: + id: TX-Queue ID. + random_detect: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class TxQueues(AvdIndexedList[int, TxQueuesItem]): + """Subclass of AvdIndexedList with `TxQueuesItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + TxQueues._item_type = TxQueuesItem + + class VrrpIdsItem(AvdModel): + """Subclass of AvdModel.""" + + class Advertisement(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interval": {"type": int}, "_custom_data": {"type": dict}} + interval: int | None + """Interval in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, interval: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Advertisement. + + + Subclass of AvdModel. + + Args: + interval: Interval in seconds. + _custom_data: _custom_data + + """ + + class Preempt(AvdModel): + """Subclass of AvdModel.""" + + class Delay(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"minimum": {"type": int}, "reload": {"type": int}, "_custom_data": {"type": dict}} + minimum: int | None + """Minimum preempt delay in seconds.""" + reload: int | None + """Reload preempt delay in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + minimum: int | None | UndefinedType = Undefined, + reload: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Delay. + + + Subclass of AvdModel. + + Args: + minimum: Minimum preempt delay in seconds. + reload: Reload preempt delay in seconds. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "delay": {"type": Delay}, "_custom_data": {"type": dict}} + enabled: bool + delay: Delay + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + delay: Delay | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Preempt. + + + Subclass of AvdModel. + + Args: + enabled: enabled + delay: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Timers(AvdModel): + """Subclass of AvdModel.""" + + class Delay(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"reload": {"type": int}, "_custom_data": {"type": dict}} + reload: int | None + """Delay after reload in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, reload: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Delay. + + + Subclass of AvdModel. + + Args: + reload: Delay after reload in seconds. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"delay": {"type": Delay}, "_custom_data": {"type": dict}} + delay: Delay + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, delay: Delay | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Timers. + + + Subclass of AvdModel. + + Args: + delay: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class TrackedObjectItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "decrement": {"type": int}, "shutdown": {"type": bool}, "_custom_data": {"type": dict}} + name: str + """Tracked object name.""" + decrement: int | None + """Decrement VRRP priority by 1-254.""" + shutdown: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + decrement: int | None | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TrackedObjectItem. + + + Subclass of AvdModel. + + Args: + name: Tracked object name. + decrement: Decrement VRRP priority by 1-254. + shutdown: shutdown + _custom_data: _custom_data + + """ + + class TrackedObject(AvdIndexedList[str, TrackedObjectItem]): + """Subclass of AvdIndexedList with `TrackedObjectItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + TrackedObject._item_type = TrackedObjectItem + + class Ipv4(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"address": {"type": str}, "version": {"type": int}, "_custom_data": {"type": dict}} + address: str + """Virtual IPv4 address.""" + version: Literal[2, 3] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + address: str | UndefinedType = Undefined, + version: Literal[2, 3] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4. + + + Subclass of AvdModel. + + Args: + address: Virtual IPv4 address. + version: version + _custom_data: _custom_data + + """ + + class Ipv6(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"address": {"type": str}, "_custom_data": {"type": dict}} + address: str + """Virtual IPv6 address.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, address: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Ipv6. + + + Subclass of AvdModel. + + Args: + address: Virtual IPv6 address. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "priority_level": {"type": int}, + "advertisement": {"type": Advertisement}, + "preempt": {"type": Preempt}, + "timers": {"type": Timers}, + "tracked_object": {"type": TrackedObject}, + "ipv4": {"type": Ipv4}, + "ipv6": {"type": Ipv6}, + "_custom_data": {"type": dict}, + } + id: int + """VRID.""" + priority_level: int | None + """Instance priority.""" + advertisement: Advertisement + """Subclass of AvdModel.""" + preempt: Preempt + """Subclass of AvdModel.""" + timers: Timers + """Subclass of AvdModel.""" + tracked_object: TrackedObject + """Subclass of AvdIndexedList with `TrackedObjectItem` items. Primary key is `name` (`str`).""" + ipv4: Ipv4 + """Subclass of AvdModel.""" + ipv6: Ipv6 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + priority_level: int | None | UndefinedType = Undefined, + advertisement: Advertisement | UndefinedType = Undefined, + preempt: Preempt | UndefinedType = Undefined, + timers: Timers | UndefinedType = Undefined, + tracked_object: TrackedObject | UndefinedType = Undefined, + ipv4: Ipv4 | UndefinedType = Undefined, + ipv6: Ipv6 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrrpIdsItem. + + + Subclass of AvdModel. + + Args: + id: VRID. + priority_level: Instance priority. + advertisement: Subclass of AvdModel. + preempt: Subclass of AvdModel. + timers: Subclass of AvdModel. + tracked_object: Subclass of AvdIndexedList with `TrackedObjectItem` items. Primary key is `name` (`str`). + ipv4: Subclass of AvdModel. + ipv6: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class VrrpIds(AvdIndexedList[int, VrrpIdsItem]): + """Subclass of AvdIndexedList with `VrrpIdsItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + VrrpIds._item_type = VrrpIdsItem + + class Switchport(AvdModel): + """Subclass of AvdModel.""" + + class Trunk(AvdModel): + """Subclass of AvdModel.""" + + class Groups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Groups._item_type = str + + _fields: ClassVar[dict] = { + "allowed_vlan": {"type": str}, + "native_vlan": {"type": int}, + "native_vlan_tag": {"type": bool}, + "private_vlan_secondary": {"type": bool}, + "groups": {"type": Groups}, + "_custom_data": {"type": dict}, + } + allowed_vlan: str | None + """ + VLAN ID or range(s) of VLAN IDs. + Warning: This should not be combined with + `ethernet_interfaces[].mode = trunk` and `ethernet_interface[].vlans`. + """ + native_vlan: int | None + """ + Set native VLAN when interface is in trunking mode. + Warning: This should not be combined with + `ethernet_interfaces[].native_vlan`. + """ + native_vlan_tag: bool | None + """ + If setting both native_vlan and native_vlan_tag, native_vlan_tag takes precedence. + Warning: This + should not be combined with `ethernet_interfaces[].native_vlan_tag`. + """ + private_vlan_secondary: bool | None + """ + Enable secondary VLAN mapping for a private vlan. + Warning: This should not be combined with + `ethernet_ineterfaces[].trunk_private_vlan_secondary`. + """ + groups: Groups + """ + Warning: This should not be combined with `ethernet_ineterfaces[].trunk_groups`. + + + Subclass of + AvdList with `str` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + allowed_vlan: str | None | UndefinedType = Undefined, + native_vlan: int | None | UndefinedType = Undefined, + native_vlan_tag: bool | None | UndefinedType = Undefined, + private_vlan_secondary: bool | None | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Trunk. + + + Subclass of AvdModel. + + Args: + allowed_vlan: + VLAN ID or range(s) of VLAN IDs. + Warning: This should not be combined with + `ethernet_interfaces[].mode = trunk` and `ethernet_interface[].vlans`. + native_vlan: + Set native VLAN when interface is in trunking mode. + Warning: This should not be combined with + `ethernet_interfaces[].native_vlan`. + native_vlan_tag: + If setting both native_vlan and native_vlan_tag, native_vlan_tag takes precedence. + Warning: This + should not be combined with `ethernet_interfaces[].native_vlan_tag`. + private_vlan_secondary: + Enable secondary VLAN mapping for a private vlan. + Warning: This should not be combined with + `ethernet_ineterfaces[].trunk_private_vlan_secondary`. + groups: + Warning: This should not be combined with `ethernet_ineterfaces[].trunk_groups`. + + + Subclass of + AvdList with `str` items. + _custom_data: _custom_data + + """ + + class Phone(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"vlan": {"type": int}, "trunk": {"type": str}, "_custom_data": {"type": dict}} + vlan: int | None + """Warning: This should not be combined with `ethernet_interfaces[].phone.vlan`.""" + trunk: Literal["tagged", "tagged phone", "untagged", "untagged phone"] | None + """Warning: This should not be combined with `ethernet_interfaces[].phone.trunk`.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + vlan: int | None | UndefinedType = Undefined, + trunk: Literal["tagged", "tagged phone", "untagged", "untagged phone"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Phone. + + + Subclass of AvdModel. + + Args: + vlan: Warning: This should not be combined with `ethernet_interfaces[].phone.vlan`. + trunk: Warning: This should not be combined with `ethernet_interfaces[].phone.trunk`. + _custom_data: _custom_data + + """ + + class Dot1q(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ethertype": {"type": int}, "vlan_tag": {"type": str}, "_custom_data": {"type": dict}} + ethertype: int | None + """Ethertype/TPID (Tag Protocol IDentifier) for VLAN tagged frames.""" + vlan_tag: Literal["disallowed", "required"] | None + """Allow/disallow VLAN tagged frames.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ethertype: int | None | UndefinedType = Undefined, + vlan_tag: Literal["disallowed", "required"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dot1q. + + + Subclass of AvdModel. + + Args: + ethertype: Ethertype/TPID (Tag Protocol IDentifier) for VLAN tagged frames. + vlan_tag: Allow/disallow VLAN tagged frames. + _custom_data: _custom_data + + """ + + class VlanTranslations(AvdModel): + """Subclass of AvdModel.""" + + class DirectionInItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "field_from": {"type": str}, + "to": {"type": int}, + "dot1q_tunnel": {"type": bool}, + "inner_vlan_from": {"type": int}, + "_custom_data": {"type": dict}, + } + _field_to_key_map: ClassVar[dict] = {"field_from": "from"} + _key_to_field_map: ClassVar[dict] = {"from": "field_from"} + field_from: str + """VLAN ID or range of VLAN IDs to map from. Range 1-4094.""" + to: int + """VLAN ID to map to.""" + dot1q_tunnel: bool | None + inner_vlan_from: int | None + """Inner VLAN ID to map from.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + field_from: str | UndefinedType = Undefined, + to: int | UndefinedType = Undefined, + dot1q_tunnel: bool | None | UndefinedType = Undefined, + inner_vlan_from: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionInItem. + + + Subclass of AvdModel. + + Args: + field_from: VLAN ID or range of VLAN IDs to map from. Range 1-4094. + to: VLAN ID to map to. + dot1q_tunnel: dot1q_tunnel + inner_vlan_from: Inner VLAN ID to map from. + _custom_data: _custom_data + + """ + + class DirectionIn(AvdList[DirectionInItem]): + """Subclass of AvdList with `DirectionInItem` items.""" + + DirectionIn._item_type = DirectionInItem + + class DirectionOutItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "field_from": {"type": str}, + "to": {"type": int}, + "dot1q_tunnel_to": {"type": str}, + "inner_vlan_to": {"type": int}, + "_custom_data": {"type": dict}, + } + _field_to_key_map: ClassVar[dict] = {"field_from": "from"} + _key_to_field_map: ClassVar[dict] = {"from": "field_from"} + field_from: str + """VLAN ID or range of VLAN IDs to map from. Range 1-4094.""" + to: int | None + """VLAN ID to map to.""" + dot1q_tunnel_to: str | None + """ + VLAN ID or range of VLAN IDs or "all". Range 1-4094. + This takes precedence over `to` and + `inner_vlan_to`. + """ + inner_vlan_to: int | None + """Inner VLAN ID to map to.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + field_from: str | UndefinedType = Undefined, + to: int | None | UndefinedType = Undefined, + dot1q_tunnel_to: str | None | UndefinedType = Undefined, + inner_vlan_to: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionOutItem. + + + Subclass of AvdModel. + + Args: + field_from: VLAN ID or range of VLAN IDs to map from. Range 1-4094. + to: VLAN ID to map to. + dot1q_tunnel_to: + VLAN ID or range of VLAN IDs or "all". Range 1-4094. + This takes precedence over `to` and + `inner_vlan_to`. + inner_vlan_to: Inner VLAN ID to map to. + _custom_data: _custom_data + + """ + + class DirectionOut(AvdList[DirectionOutItem]): + """Subclass of AvdList with `DirectionOutItem` items.""" + + DirectionOut._item_type = DirectionOutItem + + class DirectionBothItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "field_from": {"type": str}, + "to": {"type": int}, + "dot1q_tunnel": {"type": bool}, + "inner_vlan_from": {"type": int}, + "network": {"type": bool}, + "_custom_data": {"type": dict}, + } + _field_to_key_map: ClassVar[dict] = {"field_from": "from"} + _key_to_field_map: ClassVar[dict] = {"from": "field_from"} + field_from: str + """VLAN ID or range of VLAN IDs to map from. Range 1-4094.""" + to: int + """VLAN ID to map to.""" + dot1q_tunnel: bool | None + inner_vlan_from: int | None + """Inner VLAN ID to map from.""" + network: bool | None + """ + Enable use of network-side VLAN ID. + This setting can only be enabled when `inner_vlan_from` is + defined. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + field_from: str | UndefinedType = Undefined, + to: int | UndefinedType = Undefined, + dot1q_tunnel: bool | None | UndefinedType = Undefined, + inner_vlan_from: int | None | UndefinedType = Undefined, + network: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionBothItem. + + + Subclass of AvdModel. + + Args: + field_from: VLAN ID or range of VLAN IDs to map from. Range 1-4094. + to: VLAN ID to map to. + dot1q_tunnel: dot1q_tunnel + inner_vlan_from: Inner VLAN ID to map from. + network: + Enable use of network-side VLAN ID. + This setting can only be enabled when `inner_vlan_from` is + defined. + _custom_data: _custom_data + + """ + + class DirectionBoth(AvdList[DirectionBothItem]): + """Subclass of AvdList with `DirectionBothItem` items.""" + + DirectionBoth._item_type = DirectionBothItem + + _fields: ClassVar[dict] = { + "in_required": {"type": bool}, + "out_required": {"type": bool}, + "direction_in": {"type": DirectionIn}, + "direction_out": {"type": DirectionOut}, + "direction_both": {"type": DirectionBoth}, + "_custom_data": {"type": dict}, + } + in_required: bool | None + """Drop the ingress traffic that do not match any VLAN mapping.""" + out_required: bool | None + """Drop the egress traffic that do not match any VLAN mapping.""" + direction_in: DirectionIn + """ + Map ingress traffic only. + + Subclass of AvdList with `DirectionInItem` items. + """ + direction_out: DirectionOut + """ + Map egress traffic only. + + Subclass of AvdList with `DirectionOutItem` items. + """ + direction_both: DirectionBoth + """ + Map both egress and ingress traffic. + + Subclass of AvdList with `DirectionBothItem` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + in_required: bool | None | UndefinedType = Undefined, + out_required: bool | None | UndefinedType = Undefined, + direction_in: DirectionIn | UndefinedType = Undefined, + direction_out: DirectionOut | UndefinedType = Undefined, + direction_both: DirectionBoth | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VlanTranslations. + + + Subclass of AvdModel. + + Args: + in_required: Drop the ingress traffic that do not match any VLAN mapping. + out_required: Drop the egress traffic that do not match any VLAN mapping. + direction_in: + Map ingress traffic only. + + Subclass of AvdList with `DirectionInItem` items. + direction_out: + Map egress traffic only. + + Subclass of AvdList with `DirectionOutItem` items. + direction_both: + Map both egress and ingress traffic. + + Subclass of AvdList with `DirectionBothItem` items. + _custom_data: _custom_data + + """ + + class BackupLink(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interface": {"type": str}, "prefer_vlan": {"type": str}, "_custom_data": {"type": dict}} + interface: str | None + """Backup interface. Example - Ethernet4, Vlan10 etc.""" + prefer_vlan: str | None + """VLANs to carry on the backup interface (1-4094).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interface: str | None | UndefinedType = Undefined, + prefer_vlan: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BackupLink. + + + Subclass of AvdModel. + + Args: + interface: Backup interface. Example - Ethernet4, Vlan10 etc. + prefer_vlan: VLANs to carry on the backup interface (1-4094). + _custom_data: _custom_data + + """ + + class Backup(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "dest_macaddr": {"type": str}, + "initial_mac_move_delay": {"type": int}, + "mac_move_burst": {"type": int}, + "mac_move_burst_interval": {"type": int}, + "preemption_delay": {"type": int}, + "_custom_data": {"type": dict}, + } + dest_macaddr: str | None + """ + Destination MAC address for MAC move updates. + The mac address should be multicast or broadcast. + Example: 01:00:00:00:00:00 + """ + initial_mac_move_delay: int | None + """Initial MAC move delay in milliseconds.""" + mac_move_burst: int | None + """Size of MAC move bursts.""" + mac_move_burst_interval: int | None + """MAC move burst interval in milliseconds.""" + preemption_delay: int | None + """Preemption delay in milliseconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dest_macaddr: str | None | UndefinedType = Undefined, + initial_mac_move_delay: int | None | UndefinedType = Undefined, + mac_move_burst: int | None | UndefinedType = Undefined, + mac_move_burst_interval: int | None | UndefinedType = Undefined, + preemption_delay: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Backup. + + + Subclass of AvdModel. + + Args: + dest_macaddr: + Destination MAC address for MAC move updates. + The mac address should be multicast or broadcast. + Example: 01:00:00:00:00:00 + initial_mac_move_delay: Initial MAC move delay in milliseconds. + mac_move_burst: Size of MAC move bursts. + mac_move_burst_interval: MAC move burst interval in milliseconds. + preemption_delay: Preemption delay in milliseconds. + _custom_data: _custom_data + + """ + + class PortSecurity(AvdModel): + """Subclass of AvdModel.""" + + class MacAddressMaximum(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"disabled": {"type": bool}, "limit": {"type": int}, "_custom_data": {"type": dict}} + disabled: bool | None + """Disable port level check for port security (only in violation 'shutdown' mode).""" + limit: int | None + """MAC address limit.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + disabled: bool | None | UndefinedType = Undefined, + limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MacAddressMaximum. + + + Subclass of AvdModel. + + Args: + disabled: Disable port level check for port security (only in violation 'shutdown' mode). + limit: MAC address limit. + _custom_data: _custom_data + + """ + + class Violation(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"mode": {"type": str}, "protect_log": {"type": bool}, "_custom_data": {"type": dict}} + mode: Literal["shutdown", "protect"] | None + """Configure port security mode.""" + protect_log: bool | None + """Log new addresses seen after limit is reached in protect mode.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["shutdown", "protect"] | None | UndefinedType = Undefined, + protect_log: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Violation. + + + Subclass of AvdModel. + + Args: + mode: Configure port security mode. + protect_log: Log new addresses seen after limit is reached in protect mode. + _custom_data: _custom_data + + """ + + class VlansItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"range": {"type": str}, "mac_address_maximum": {"type": int}, "_custom_data": {"type": dict}} + range: str + """ + VLAN ID or range(s) of VLAN IDs, <1-4094>. + Example: + - 3 + - 1,3 + - 1-10 + """ + mac_address_maximum: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + range: str | UndefinedType = Undefined, + mac_address_maximum: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VlansItem. + + + Subclass of AvdModel. + + Args: + range: + VLAN ID or range(s) of VLAN IDs, <1-4094>. + Example: # fmt: skip + - 3 + - 1,3 + - 1-10 + mac_address_maximum: mac_address_maximum + _custom_data: _custom_data + + """ + + class Vlans(AvdIndexedList[str, VlansItem]): + """Subclass of AvdIndexedList with `VlansItem` items. Primary key is `range` (`str`).""" + + _primary_key: ClassVar[str] = "range" + + Vlans._item_type = VlansItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "mac_address_maximum": {"type": MacAddressMaximum}, + "violation": {"type": Violation}, + "vlan_default_mac_address_maximum": {"type": int}, + "vlans": {"type": Vlans}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + mac_address_maximum: MacAddressMaximum + """ + Maximum number of MAC addresses allowed on the interface. + + Subclass of AvdModel. + """ + violation: Violation + """ + Configure violation mode (shutdown or protect), EOS default is 'shutdown'. + + Subclass of AvdModel. + """ + vlan_default_mac_address_maximum: int | None + """Default maximum MAC addresses for all VLANs on this interface.""" + vlans: Vlans + """Subclass of AvdIndexedList with `VlansItem` items. Primary key is `range` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + mac_address_maximum: MacAddressMaximum | UndefinedType = Undefined, + violation: Violation | UndefinedType = Undefined, + vlan_default_mac_address_maximum: int | None | UndefinedType = Undefined, + vlans: Vlans | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PortSecurity. + + + Subclass of AvdModel. + + Args: + enabled: enabled + mac_address_maximum: + Maximum number of MAC addresses allowed on the interface. + + Subclass of AvdModel. + violation: + Configure violation mode (shutdown or protect), EOS default is 'shutdown'. + + Subclass of AvdModel. + vlan_default_mac_address_maximum: Default maximum MAC addresses for all VLANs on this interface. + vlans: Subclass of AvdIndexedList with `VlansItem` items. Primary key is `range` (`str`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "mode": {"type": str}, + "access_vlan": {"type": int}, + "trunk": {"type": Trunk}, + "phone": {"type": Phone}, + "pvlan_mapping": {"type": str}, + "dot1q": {"type": Dot1q}, + "source_interface": {"type": str}, + "vlan_translations": {"type": VlanTranslations}, + "vlan_forwarding_accept_all": {"type": bool}, + "backup_link": {"type": BackupLink}, + "backup": {"type": Backup}, + "port_security": {"type": PortSecurity}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Warning: This should not be combined with `ethernet_interfaces[].type = routed`.""" + mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None + """Warning: This should not be combined with `ethernet_interfaces[].mode`.""" + access_vlan: int | None + """ + Set VLAN when interface is in access mode. + Warning: This should not be combined with + `ethernet_interfaces[].mode = access/dot1q-tunnel` and `ethernet_interface[].vlans`. + """ + trunk: Trunk + """Subclass of AvdModel.""" + phone: Phone + """ + Warning: This should not be combined with `ethernet_interfaces[].phone`. + + Subclass of AvdModel. + """ + pvlan_mapping: str | None + """ + Secondary VLAN IDs of the private VLAN mapping. + Warning: This should not be combined with + `ethernet_interfaces[].pvlan_mapping`. + """ + dot1q: Dot1q + """Subclass of AvdModel.""" + source_interface: Literal["tx", "tx multicast"] | None + """ + tx: Allow bridged traffic to go out of the source interface. + tx multicast: Allow multicast traffic + only to go out of the source interface. + """ + vlan_translations: VlanTranslations + """ + VLAN Translation mappings. + Warning: This should not be combined with + `ethernet_interfaces[].vlan_translations`. + + Subclass of AvdModel. + """ + vlan_forwarding_accept_all: bool | None + backup_link: BackupLink + """Subclass of AvdModel.""" + backup: Backup + """ + The `backup_link` is required for this setting. + + Subclass of AvdModel. + """ + port_security: PortSecurity + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None | UndefinedType = Undefined, + access_vlan: int | None | UndefinedType = Undefined, + trunk: Trunk | UndefinedType = Undefined, + phone: Phone | UndefinedType = Undefined, + pvlan_mapping: str | None | UndefinedType = Undefined, + dot1q: Dot1q | UndefinedType = Undefined, + source_interface: Literal["tx", "tx multicast"] | None | UndefinedType = Undefined, + vlan_translations: VlanTranslations | UndefinedType = Undefined, + vlan_forwarding_accept_all: bool | None | UndefinedType = Undefined, + backup_link: BackupLink | UndefinedType = Undefined, + backup: Backup | UndefinedType = Undefined, + port_security: PortSecurity | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Switchport. + + + Subclass of AvdModel. + + Args: + enabled: Warning: This should not be combined with `ethernet_interfaces[].type = routed`. + mode: Warning: This should not be combined with `ethernet_interfaces[].mode`. + access_vlan: + Set VLAN when interface is in access mode. + Warning: This should not be combined with + `ethernet_interfaces[].mode = access/dot1q-tunnel` and `ethernet_interface[].vlans`. + trunk: Subclass of AvdModel. + phone: + Warning: This should not be combined with `ethernet_interfaces[].phone`. + + Subclass of AvdModel. + pvlan_mapping: + Secondary VLAN IDs of the private VLAN mapping. + Warning: This should not be combined with + `ethernet_interfaces[].pvlan_mapping`. + dot1q: Subclass of AvdModel. + source_interface: + tx: Allow bridged traffic to go out of the source interface. + tx multicast: Allow multicast traffic + only to go out of the source interface. + vlan_translations: + VLAN Translation mappings. + Warning: This should not be combined with + `ethernet_interfaces[].vlan_translations`. + + Subclass of AvdModel. + vlan_forwarding_accept_all: vlan_forwarding_accept_all + backup_link: Subclass of AvdModel. + backup: + The `backup_link` is required for this setting. + + Subclass of AvdModel. + port_security: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "description": {"type": str}, + "shutdown": {"type": bool}, + "load_interval": {"type": int}, + "speed": {"type": str}, + "mtu": {"type": int}, + "l2_mtu": {"type": int}, + "l2_mru": {"type": int}, + "vlans": {"type": str}, + "native_vlan": {"type": int}, + "native_vlan_tag": {"type": bool}, + "mode": {"type": str}, + "phone": {"type": Phone}, + "l2_protocol": {"type": L2Protocol}, + "mac_timestamp": {"type": str}, + "trunk_groups": {"type": TrunkGroups}, + "type": {"type": str}, + "snmp_trap_link_change": {"type": bool}, + "address_locking": {"type": AddressLocking}, + "flowcontrol": {"type": Flowcontrol}, + "vrf": {"type": str}, + "flow_tracker": {"type": FlowTracker}, + "error_correction_encoding": {"type": ErrorCorrectionEncoding}, + "link_tracking_groups": {"type": LinkTrackingGroups}, + "link_tracking": {"type": LinkTracking}, + "evpn_ethernet_segment": {"type": EvpnEthernetSegment}, + "encapsulation_dot1q_vlan": {"type": int}, + "encapsulation_dot1q": {"type": EncapsulationDot1q}, + "encapsulation_vlan": {"type": EncapsulationVlan}, + "vlan_id": {"type": int}, + "ip_address": {"type": str}, + "ip_address_secondaries": {"type": IpAddressSecondaries}, + "ip_verify_unicast_source_reachable_via": {"type": str}, + "dhcp_client_accept_default_route": {"type": bool}, + "dhcp_server_ipv4": {"type": bool}, + "dhcp_server_ipv6": {"type": bool}, + "ip_helpers": {"type": IpHelpers}, + "ip_nat": {"type": IpNat}, + "ipv6_enable": {"type": bool}, + "ipv6_address": {"type": str}, + "ipv6_address_link_local": {"type": str}, + "ipv6_nd_ra_disabled": {"type": bool}, + "ipv6_nd_managed_config_flag": {"type": bool}, + "ipv6_nd_prefixes": {"type": Ipv6NdPrefixes}, + "ipv6_dhcp_relay_destinations": {"type": Ipv6DhcpRelayDestinations}, + "access_group_in": {"type": str}, + "access_group_out": {"type": str}, + "ipv6_access_group_in": {"type": str}, + "ipv6_access_group_out": {"type": str}, + "mac_access_group_in": {"type": str}, + "mac_access_group_out": {"type": str}, + "multicast": {"type": Multicast}, + "ospf_network_point_to_point": {"type": bool}, + "ospf_area": {"type": str}, + "ospf_cost": {"type": int}, + "ospf_authentication": {"type": str}, + "ospf_authentication_key": {"type": str}, + "ospf_message_digest_keys": {"type": OspfMessageDigestKeys}, + "pim": {"type": Pim}, + "mac_security": {"type": MacSecurity}, + "tcp_mss_ceiling": {"type": TcpMssCeiling}, + "channel_group": {"type": ChannelGroup}, + "isis_enable": {"type": str}, + "isis_bfd": {"type": bool}, + "isis_passive": {"type": bool}, + "isis_metric": {"type": int}, + "isis_network_point_to_point": {"type": bool}, + "isis_circuit_type": {"type": str}, + "isis_hello_padding": {"type": bool}, + "isis_authentication_mode": {"type": str}, + "isis_authentication_key": {"type": str}, + "isis_authentication": {"type": IsisAuthentication}, + "poe": {"type": Poe}, + "ptp": {"type": Ptp}, + "profile": {"type": str}, + "storm_control": {"type": StormControl}, + "logging": {"type": Logging}, + "lldp": {"type": Lldp}, + "trunk_private_vlan_secondary": {"type": bool}, + "pvlan_mapping": {"type": str}, + "vlan_translations": {"type": VlanTranslations}, + "dot1x": {"type": Dot1x}, + "service_profile": {"type": str}, + "shape": {"type": Shape}, + "qos": {"type": Qos}, + "spanning_tree_bpdufilter": {"type": str}, + "spanning_tree_bpduguard": {"type": str}, + "spanning_tree_guard": {"type": str}, + "spanning_tree_portfast": {"type": str}, + "vmtracer": {"type": bool}, + "priority_flow_control": {"type": PriorityFlowControl}, + "bfd": {"type": Bfd}, + "service_policy": {"type": ServicePolicy}, + "mpls": {"type": Mpls}, + "lacp_timer": {"type": LacpTimer}, + "lacp_port_priority": {"type": int}, + "transceiver": {"type": Transceiver}, + "ip_proxy_arp": {"type": bool}, + "traffic_policy": {"type": TrafficPolicy}, + "bgp": {"type": Bgp}, + "ip_igmp_host_proxy": {"type": IpIgmpHostProxy}, + "peer": {"type": str}, + "peer_interface": {"type": str}, + "peer_type": {"type": str}, + "sflow": {"type": Sflow}, + "sync_e": {"type": SyncE}, + "port_profile": {"type": str}, + "uc_tx_queues": {"type": UcTxQueues}, + "tx_queues": {"type": TxQueues}, + "vrrp_ids": {"type": VrrpIds}, + "validate_state": {"type": bool}, + "validate_lldp": {"type": bool}, + "switchport": {"type": Switchport}, + "eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + description: str | None + shutdown: bool | None + load_interval: int | None + """Interval in seconds for updating interface counters.""" + speed: str | None + """ + Speed should be set in the format `` or `forced ` or `auto + `. + """ + mtu: int | None + l2_mtu: int | None + """"l2_mtu" should only be defined for platforms supporting the "l2 mtu" CLI.""" + l2_mru: int | None + """"l2_mru" should only be defined for platforms supporting the "l2 mru" CLI.""" + vlans: str | None + """ + List of switchport vlans as string. + For a trunk port this would be a range like "1-200,300". + For an + access port this would be a single vlan "123". + """ + native_vlan: int | None + native_vlan_tag: bool | None + """If setting both native_vlan and native_vlan_tag, native_vlan_tag takes precedence.""" + mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None + phone: Phone + """Subclass of AvdModel.""" + l2_protocol: L2Protocol + """Subclass of AvdModel.""" + mac_timestamp: Literal["before-fcs", "replace-fcs", "header"] | None + """ + header: Insert timestamp in ethernet header. Supported on platforms like 7500E/R and 7280E/R. + before-fcs: Insert timestamp before fcs field. Supported on platforms like 7150. + replace-fcs: + Replace fcs field with timestamp. + """ + trunk_groups: TrunkGroups + """Subclass of AvdList with `str` items.""" + type: Literal["routed", "switched", "l3dot1q", "l2dot1q", "port-channel-member"] | None + """ + l3dot1q and l2dot1q are used for sub-interfaces. The parent interface should be defined as routed. + The `type = switched/routed` should not be combined with `switchport`. + """ + snmp_trap_link_change: bool | None + address_locking: AddressLocking + """Subclass of AvdModel.""" + flowcontrol: Flowcontrol + """Subclass of AvdModel.""" + vrf: str | None + """VRF name.""" + flow_tracker: FlowTracker + """Subclass of AvdModel.""" + error_correction_encoding: ErrorCorrectionEncoding + """Subclass of AvdModel.""" + link_tracking_groups: LinkTrackingGroups + """Subclass of AvdIndexedList with `LinkTrackingGroupsItem` items. Primary key is `name` (`str`).""" + link_tracking: LinkTracking + """Subclass of AvdModel.""" + evpn_ethernet_segment: EvpnEthernetSegment + """Subclass of AvdModel.""" + encapsulation_dot1q_vlan: int | None + """VLAN tag to configure on sub-interface.""" + encapsulation_dot1q: EncapsulationDot1q + """ + Warning: `encapsulation_dot1q` should not be combined with `ethernet_interfaces[].type: l3dot1q` or + `ethernet_interfaces[].type: l2dot1q`. + + Subclass of AvdModel. + """ + encapsulation_vlan: EncapsulationVlan + """ + This setting can only be applied to sub-interfaces on EOS. + Warning: `encapsulation_vlan` should not + be combined with `ethernet_interfaces[].type: l3dot1q` or `ethernet_interfaces[].type: l2dot1q`. + Subclass of AvdModel. + """ + vlan_id: int | None + """ + This setting can only be applied to sub-interfaces on EOS. + Warning: `vlan_id` should not be combined + with `ethernet_interfaces[].type == l2dot1q`. + """ + ip_address: str | None + """IPv4 address/mask or "dhcp".""" + ip_address_secondaries: IpAddressSecondaries + """Subclass of AvdList with `str` items.""" + ip_verify_unicast_source_reachable_via: Literal["any", "rx"] | None + dhcp_client_accept_default_route: bool | None + """Install default-route obtained via DHCP.""" + dhcp_server_ipv4: bool | None + """Enable IPv4 DHCP server.""" + dhcp_server_ipv6: bool | None + """Enable IPv6 DHCP server.""" + ip_helpers: IpHelpers + """Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is `ip_helper` (`str`).""" + ip_nat: IpNat + """Subclass of AvdModel.""" + ipv6_enable: bool | None + ipv6_address: str | None + ipv6_address_link_local: str | None + """Link local IPv6 address/mask.""" + ipv6_nd_ra_disabled: bool | None + ipv6_nd_managed_config_flag: bool | None + ipv6_nd_prefixes: Ipv6NdPrefixes + """Subclass of AvdIndexedList with `Ipv6NdPrefixesItem` items. Primary key is `ipv6_prefix` (`str`).""" + ipv6_dhcp_relay_destinations: Ipv6DhcpRelayDestinations + """ + Subclass of AvdIndexedList with `Ipv6DhcpRelayDestinationsItem` items. Primary key is `address` + (`str`). + """ + access_group_in: str | None + """Access list name.""" + access_group_out: str | None + """Access list name.""" + ipv6_access_group_in: str | None + """IPv6 access list name.""" + ipv6_access_group_out: str | None + """IPv6 access list name.""" + mac_access_group_in: str | None + """MAC access list name.""" + mac_access_group_out: str | None + """MAC access list name.""" + multicast: Multicast + """ + Boundaries can be either 1 ACL or a list of multicast IP address_range(s)/prefix but not combination + of both. + + Subclass of AvdModel. + """ + ospf_network_point_to_point: bool | None + ospf_area: str | None + ospf_cost: int | None + ospf_authentication: Literal["none", "simple", "message-digest"] | None + ospf_authentication_key: str | None + """Encrypted password - only type 7 supported.""" + ospf_message_digest_keys: OspfMessageDigestKeys + """Subclass of AvdIndexedList with `OspfMessageDigestKeysItem` items. Primary key is `id` (`int`).""" + pim: Pim + """Subclass of AvdModel.""" + mac_security: MacSecurity + """Subclass of AvdModel.""" + tcp_mss_ceiling: TcpMssCeiling + """ + The TCP MSS clamping feature involves clamping the maximum segment size (MSS) in the TCP header + of + TCP SYN packets if it exceeds the configured MSS ceiling limit for the interface. + + Subclass of + AvdModel. + """ + channel_group: ChannelGroup + """Subclass of AvdModel.""" + isis_enable: str | None + """ISIS instance.""" + isis_bfd: bool | None + """Enable BFD for ISIS.""" + isis_passive: bool | None + isis_metric: int | None + isis_network_point_to_point: bool | None + isis_circuit_type: Literal["level-1-2", "level-1", "level-2"] | None + isis_hello_padding: bool | None + isis_authentication_mode: Literal["text", "md5"] | None + isis_authentication_key: str | None + """Type-7 encrypted password.""" + isis_authentication: IsisAuthentication + """ + This key should not be mixed with ethernet_interfaces[].isis_authentication_mode or + ethernet_interfaces[].isis_authentication_key. + + Subclass of AvdModel. + """ + poe: Poe + """Subclass of AvdModel.""" + ptp: Ptp + """Subclass of AvdModel.""" + profile: str | None + """Interface profile.""" + storm_control: StormControl + """Subclass of AvdModel.""" + logging: Logging + """Subclass of AvdModel.""" + lldp: Lldp + """Subclass of AvdModel.""" + trunk_private_vlan_secondary: bool | None + pvlan_mapping: str | None + """List of vlans as string.""" + vlan_translations: VlanTranslations + """Subclass of AvdList with `VlanTranslationsItem` items.""" + dot1x: Dot1x + """ + 802.1x + + Subclass of AvdModel. + """ + service_profile: str | None + """QOS profile.""" + shape: Shape + """Subclass of AvdModel.""" + qos: Qos + """Subclass of AvdModel.""" + spanning_tree_bpdufilter: Literal["enabled", "disabled", "True", "False", "true", "false"] | None + spanning_tree_bpduguard: Literal["enabled", "disabled", "True", "False", "true", "false"] | None + spanning_tree_guard: Literal["loop", "root", "disabled"] | None + spanning_tree_portfast: Literal["edge", "network"] | None + vmtracer: bool | None + priority_flow_control: PriorityFlowControl + """Subclass of AvdModel.""" + bfd: Bfd + """Subclass of AvdModel.""" + service_policy: ServicePolicy + """Subclass of AvdModel.""" + mpls: Mpls + """Subclass of AvdModel.""" + lacp_timer: LacpTimer + """Subclass of AvdModel.""" + lacp_port_priority: int | None + transceiver: Transceiver + """Subclass of AvdModel.""" + ip_proxy_arp: bool | None + traffic_policy: TrafficPolicy + """Subclass of AvdModel.""" + bgp: Bgp + """Subclass of AvdModel.""" + ip_igmp_host_proxy: IpIgmpHostProxy + """Subclass of AvdModel.""" + peer: str | None + """Key only used for documentation or validation purposes.""" + peer_interface: str | None + """Key only used for documentation or validation purposes.""" + peer_type: str | None + """Key only used for documentation or validation purposes.""" + sflow: Sflow + """Subclass of AvdModel.""" + sync_e: SyncE + """Subclass of AvdModel.""" + port_profile: str | None + """Key only used for documentation or validation purposes.""" + uc_tx_queues: UcTxQueues + """Subclass of AvdIndexedList with `UcTxQueuesItem` items. Primary key is `id` (`int`).""" + tx_queues: TxQueues + """Subclass of AvdIndexedList with `TxQueuesItem` items. Primary key is `id` (`int`).""" + vrrp_ids: VrrpIds + """ + VRRP model. + + Subclass of AvdIndexedList with `VrrpIdsItem` items. Primary key is `id` (`int`). + """ + validate_state: bool | None + """ + Set to false to disable interface state and LLDP topology validation performed by the + `eos_validate_state` role. + """ + validate_lldp: bool | None + """Set to false to disable the LLDP topology validation performed by the `eos_validate_state` role.""" + switchport: Switchport + """ + This should not be combined with `ethernet_interfaces[].type = switched/routed`. + + Subclass of + AvdModel. + """ + eos_cli: str | None + """Multiline EOS CLI rendered directly on the ethernet interface in the final EOS configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + load_interval: int | None | UndefinedType = Undefined, + speed: str | None | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + l2_mtu: int | None | UndefinedType = Undefined, + l2_mru: int | None | UndefinedType = Undefined, + vlans: str | None | UndefinedType = Undefined, + native_vlan: int | None | UndefinedType = Undefined, + native_vlan_tag: bool | None | UndefinedType = Undefined, + mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None | UndefinedType = Undefined, + phone: Phone | UndefinedType = Undefined, + l2_protocol: L2Protocol | UndefinedType = Undefined, + mac_timestamp: Literal["before-fcs", "replace-fcs", "header"] | None | UndefinedType = Undefined, + trunk_groups: TrunkGroups | UndefinedType = Undefined, + type: Literal["routed", "switched", "l3dot1q", "l2dot1q", "port-channel-member"] | None | UndefinedType = Undefined, + snmp_trap_link_change: bool | None | UndefinedType = Undefined, + address_locking: AddressLocking | UndefinedType = Undefined, + flowcontrol: Flowcontrol | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + flow_tracker: FlowTracker | UndefinedType = Undefined, + error_correction_encoding: ErrorCorrectionEncoding | UndefinedType = Undefined, + link_tracking_groups: LinkTrackingGroups | UndefinedType = Undefined, + link_tracking: LinkTracking | UndefinedType = Undefined, + evpn_ethernet_segment: EvpnEthernetSegment | UndefinedType = Undefined, + encapsulation_dot1q_vlan: int | None | UndefinedType = Undefined, + encapsulation_dot1q: EncapsulationDot1q | UndefinedType = Undefined, + encapsulation_vlan: EncapsulationVlan | UndefinedType = Undefined, + vlan_id: int | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + ip_address_secondaries: IpAddressSecondaries | UndefinedType = Undefined, + ip_verify_unicast_source_reachable_via: Literal["any", "rx"] | None | UndefinedType = Undefined, + dhcp_client_accept_default_route: bool | None | UndefinedType = Undefined, + dhcp_server_ipv4: bool | None | UndefinedType = Undefined, + dhcp_server_ipv6: bool | None | UndefinedType = Undefined, + ip_helpers: IpHelpers | UndefinedType = Undefined, + ip_nat: IpNat | UndefinedType = Undefined, + ipv6_enable: bool | None | UndefinedType = Undefined, + ipv6_address: str | None | UndefinedType = Undefined, + ipv6_address_link_local: str | None | UndefinedType = Undefined, + ipv6_nd_ra_disabled: bool | None | UndefinedType = Undefined, + ipv6_nd_managed_config_flag: bool | None | UndefinedType = Undefined, + ipv6_nd_prefixes: Ipv6NdPrefixes | UndefinedType = Undefined, + ipv6_dhcp_relay_destinations: Ipv6DhcpRelayDestinations | UndefinedType = Undefined, + access_group_in: str | None | UndefinedType = Undefined, + access_group_out: str | None | UndefinedType = Undefined, + ipv6_access_group_in: str | None | UndefinedType = Undefined, + ipv6_access_group_out: str | None | UndefinedType = Undefined, + mac_access_group_in: str | None | UndefinedType = Undefined, + mac_access_group_out: str | None | UndefinedType = Undefined, + multicast: Multicast | UndefinedType = Undefined, + ospf_network_point_to_point: bool | None | UndefinedType = Undefined, + ospf_area: str | None | UndefinedType = Undefined, + ospf_cost: int | None | UndefinedType = Undefined, + ospf_authentication: Literal["none", "simple", "message-digest"] | None | UndefinedType = Undefined, + ospf_authentication_key: str | None | UndefinedType = Undefined, + ospf_message_digest_keys: OspfMessageDigestKeys | UndefinedType = Undefined, + pim: Pim | UndefinedType = Undefined, + mac_security: MacSecurity | UndefinedType = Undefined, + tcp_mss_ceiling: TcpMssCeiling | UndefinedType = Undefined, + channel_group: ChannelGroup | UndefinedType = Undefined, + isis_enable: str | None | UndefinedType = Undefined, + isis_bfd: bool | None | UndefinedType = Undefined, + isis_passive: bool | None | UndefinedType = Undefined, + isis_metric: int | None | UndefinedType = Undefined, + isis_network_point_to_point: bool | None | UndefinedType = Undefined, + isis_circuit_type: Literal["level-1-2", "level-1", "level-2"] | None | UndefinedType = Undefined, + isis_hello_padding: bool | None | UndefinedType = Undefined, + isis_authentication_mode: Literal["text", "md5"] | None | UndefinedType = Undefined, + isis_authentication_key: str | None | UndefinedType = Undefined, + isis_authentication: IsisAuthentication | UndefinedType = Undefined, + poe: Poe | UndefinedType = Undefined, + ptp: Ptp | UndefinedType = Undefined, + profile: str | None | UndefinedType = Undefined, + storm_control: StormControl | UndefinedType = Undefined, + logging: Logging | UndefinedType = Undefined, + lldp: Lldp | UndefinedType = Undefined, + trunk_private_vlan_secondary: bool | None | UndefinedType = Undefined, + pvlan_mapping: str | None | UndefinedType = Undefined, + vlan_translations: VlanTranslations | UndefinedType = Undefined, + dot1x: Dot1x | UndefinedType = Undefined, + service_profile: str | None | UndefinedType = Undefined, + shape: Shape | UndefinedType = Undefined, + qos: Qos | UndefinedType = Undefined, + spanning_tree_bpdufilter: Literal["enabled", "disabled", "True", "False", "true", "false"] | None | UndefinedType = Undefined, + spanning_tree_bpduguard: Literal["enabled", "disabled", "True", "False", "true", "false"] | None | UndefinedType = Undefined, + spanning_tree_guard: Literal["loop", "root", "disabled"] | None | UndefinedType = Undefined, + spanning_tree_portfast: Literal["edge", "network"] | None | UndefinedType = Undefined, + vmtracer: bool | None | UndefinedType = Undefined, + priority_flow_control: PriorityFlowControl | UndefinedType = Undefined, + bfd: Bfd | UndefinedType = Undefined, + service_policy: ServicePolicy | UndefinedType = Undefined, + mpls: Mpls | UndefinedType = Undefined, + lacp_timer: LacpTimer | UndefinedType = Undefined, + lacp_port_priority: int | None | UndefinedType = Undefined, + transceiver: Transceiver | UndefinedType = Undefined, + ip_proxy_arp: bool | None | UndefinedType = Undefined, + traffic_policy: TrafficPolicy | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + ip_igmp_host_proxy: IpIgmpHostProxy | UndefinedType = Undefined, + peer: str | None | UndefinedType = Undefined, + peer_interface: str | None | UndefinedType = Undefined, + peer_type: str | None | UndefinedType = Undefined, + sflow: Sflow | UndefinedType = Undefined, + sync_e: SyncE | UndefinedType = Undefined, + port_profile: str | None | UndefinedType = Undefined, + uc_tx_queues: UcTxQueues | UndefinedType = Undefined, + tx_queues: TxQueues | UndefinedType = Undefined, + vrrp_ids: VrrpIds | UndefinedType = Undefined, + validate_state: bool | None | UndefinedType = Undefined, + validate_lldp: bool | None | UndefinedType = Undefined, + switchport: Switchport | UndefinedType = Undefined, + eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EthernetInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: name + description: description + shutdown: shutdown + load_interval: Interval in seconds for updating interface counters. + speed: + Speed should be set in the format `` or `forced ` or `auto + `. + mtu: mtu + l2_mtu: "l2_mtu" should only be defined for platforms supporting the "l2 mtu" CLI. + l2_mru: "l2_mru" should only be defined for platforms supporting the "l2 mru" CLI. + vlans: + List of switchport vlans as string. + For a trunk port this would be a range like "1-200,300". + For an + access port this would be a single vlan "123". + native_vlan: native_vlan + native_vlan_tag: If setting both native_vlan and native_vlan_tag, native_vlan_tag takes precedence. + mode: mode + phone: Subclass of AvdModel. + l2_protocol: Subclass of AvdModel. + mac_timestamp: + header: Insert timestamp in ethernet header. Supported on platforms like 7500E/R and 7280E/R. + before-fcs: Insert timestamp before fcs field. Supported on platforms like 7150. + replace-fcs: + Replace fcs field with timestamp. + trunk_groups: Subclass of AvdList with `str` items. + type: + l3dot1q and l2dot1q are used for sub-interfaces. The parent interface should be defined as routed. + The `type = switched/routed` should not be combined with `switchport`. + snmp_trap_link_change: snmp_trap_link_change + address_locking: Subclass of AvdModel. + flowcontrol: Subclass of AvdModel. + vrf: VRF name. + flow_tracker: Subclass of AvdModel. + error_correction_encoding: Subclass of AvdModel. + link_tracking_groups: Subclass of AvdIndexedList with `LinkTrackingGroupsItem` items. Primary key is `name` (`str`). + link_tracking: Subclass of AvdModel. + evpn_ethernet_segment: Subclass of AvdModel. + encapsulation_dot1q_vlan: VLAN tag to configure on sub-interface. + encapsulation_dot1q: + Warning: `encapsulation_dot1q` should not be combined with `ethernet_interfaces[].type: l3dot1q` or + `ethernet_interfaces[].type: l2dot1q`. + + Subclass of AvdModel. + encapsulation_vlan: + This setting can only be applied to sub-interfaces on EOS. + Warning: `encapsulation_vlan` should not + be combined with `ethernet_interfaces[].type: l3dot1q` or `ethernet_interfaces[].type: l2dot1q`. + Subclass of AvdModel. + vlan_id: + This setting can only be applied to sub-interfaces on EOS. + Warning: `vlan_id` should not be combined + with `ethernet_interfaces[].type == l2dot1q`. + ip_address: IPv4 address/mask or "dhcp". + ip_address_secondaries: Subclass of AvdList with `str` items. + ip_verify_unicast_source_reachable_via: ip_verify_unicast_source_reachable_via + dhcp_client_accept_default_route: Install default-route obtained via DHCP. + dhcp_server_ipv4: Enable IPv4 DHCP server. + dhcp_server_ipv6: Enable IPv6 DHCP server. + ip_helpers: Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is `ip_helper` (`str`). + ip_nat: Subclass of AvdModel. + ipv6_enable: ipv6_enable + ipv6_address: ipv6_address + ipv6_address_link_local: Link local IPv6 address/mask. + ipv6_nd_ra_disabled: ipv6_nd_ra_disabled + ipv6_nd_managed_config_flag: ipv6_nd_managed_config_flag + ipv6_nd_prefixes: Subclass of AvdIndexedList with `Ipv6NdPrefixesItem` items. Primary key is `ipv6_prefix` (`str`). + ipv6_dhcp_relay_destinations: + Subclass of AvdIndexedList with `Ipv6DhcpRelayDestinationsItem` items. Primary key is `address` + (`str`). + access_group_in: Access list name. + access_group_out: Access list name. + ipv6_access_group_in: IPv6 access list name. + ipv6_access_group_out: IPv6 access list name. + mac_access_group_in: MAC access list name. + mac_access_group_out: MAC access list name. + multicast: + Boundaries can be either 1 ACL or a list of multicast IP address_range(s)/prefix but not combination + of both. + + Subclass of AvdModel. + ospf_network_point_to_point: ospf_network_point_to_point + ospf_area: ospf_area + ospf_cost: ospf_cost + ospf_authentication: ospf_authentication + ospf_authentication_key: Encrypted password - only type 7 supported. + ospf_message_digest_keys: Subclass of AvdIndexedList with `OspfMessageDigestKeysItem` items. Primary key is `id` (`int`). + pim: Subclass of AvdModel. + mac_security: Subclass of AvdModel. + tcp_mss_ceiling: + The TCP MSS clamping feature involves clamping the maximum segment size (MSS) in the TCP header + of + TCP SYN packets if it exceeds the configured MSS ceiling limit for the interface. + + Subclass of + AvdModel. + channel_group: Subclass of AvdModel. + isis_enable: ISIS instance. + isis_bfd: Enable BFD for ISIS. + isis_passive: isis_passive + isis_metric: isis_metric + isis_network_point_to_point: isis_network_point_to_point + isis_circuit_type: isis_circuit_type + isis_hello_padding: isis_hello_padding + isis_authentication_mode: isis_authentication_mode + isis_authentication_key: Type-7 encrypted password. + isis_authentication: + This key should not be mixed with ethernet_interfaces[].isis_authentication_mode or + ethernet_interfaces[].isis_authentication_key. + + Subclass of AvdModel. + poe: Subclass of AvdModel. + ptp: Subclass of AvdModel. + profile: Interface profile. + storm_control: Subclass of AvdModel. + logging: Subclass of AvdModel. + lldp: Subclass of AvdModel. + trunk_private_vlan_secondary: trunk_private_vlan_secondary + pvlan_mapping: List of vlans as string. + vlan_translations: Subclass of AvdList with `VlanTranslationsItem` items. + dot1x: + 802.1x + + Subclass of AvdModel. + service_profile: QOS profile. + shape: Subclass of AvdModel. + qos: Subclass of AvdModel. + spanning_tree_bpdufilter: spanning_tree_bpdufilter + spanning_tree_bpduguard: spanning_tree_bpduguard + spanning_tree_guard: spanning_tree_guard + spanning_tree_portfast: spanning_tree_portfast + vmtracer: vmtracer + priority_flow_control: Subclass of AvdModel. + bfd: Subclass of AvdModel. + service_policy: Subclass of AvdModel. + mpls: Subclass of AvdModel. + lacp_timer: Subclass of AvdModel. + lacp_port_priority: lacp_port_priority + transceiver: Subclass of AvdModel. + ip_proxy_arp: ip_proxy_arp + traffic_policy: Subclass of AvdModel. + bgp: Subclass of AvdModel. + ip_igmp_host_proxy: Subclass of AvdModel. + peer: Key only used for documentation or validation purposes. + peer_interface: Key only used for documentation or validation purposes. + peer_type: Key only used for documentation or validation purposes. + sflow: Subclass of AvdModel. + sync_e: Subclass of AvdModel. + port_profile: Key only used for documentation or validation purposes. + uc_tx_queues: Subclass of AvdIndexedList with `UcTxQueuesItem` items. Primary key is `id` (`int`). + tx_queues: Subclass of AvdIndexedList with `TxQueuesItem` items. Primary key is `id` (`int`). + vrrp_ids: + VRRP model. + + Subclass of AvdIndexedList with `VrrpIdsItem` items. Primary key is `id` (`int`). + validate_state: + Set to false to disable interface state and LLDP topology validation performed by the + `eos_validate_state` role. + validate_lldp: Set to false to disable the LLDP topology validation performed by the `eos_validate_state` role. + switchport: + This should not be combined with `ethernet_interfaces[].type = switched/routed`. + + Subclass of + AvdModel. + eos_cli: Multiline EOS CLI rendered directly on the ethernet interface in the final EOS configuration. + _custom_data: _custom_data + + """ + + class EthernetInterfaces(AvdIndexedList[str, EthernetInterfacesItem]): + """Subclass of AvdIndexedList with `EthernetInterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + EthernetInterfaces._item_type = EthernetInterfacesItem + + class EventHandlersItem(AvdModel): + """Subclass of AvdModel.""" + + class Actions(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "bash_command": {"type": str}, + "log": {"type": bool}, + "increment_device_health_metric": {"type": str}, + "_custom_data": {"type": dict}, + } + bash_command: str | None + """Define BASH command action. Command could be multiline also.""" + log: bool | None + """Log a message when the event is triggered.""" + increment_device_health_metric: str | None + """Name of device-health metric.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + bash_command: str | None | UndefinedType = Undefined, + log: bool | None | UndefinedType = Undefined, + increment_device_health_metric: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Actions. + + + Subclass of AvdModel. + + Args: + bash_command: Define BASH command action. Command could be multiline also. + log: Log a message when the event is triggered. + increment_device_health_metric: Name of device-health metric. + _custom_data: _custom_data + + """ + + class TriggerOnCounters(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "condition": {"type": str}, + "granularity_per_source": {"type": bool}, + "poll_interval": {"type": int}, + "_custom_data": {"type": dict}, + } + condition: str | None + """Set the logical expression to evaluate.""" + granularity_per_source: bool | None + """ + Set the granularity of event counting for a wildcarded condition. + Example - + condition ( + Arad*.IptCrcErrCnt.delta > 100 ) and ( Arad*.UcFifoFullDrop.delta > 100 ) + [* wildcard is used + here] + """ + poll_interval: int | None + """Set the polling interval in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + condition: str | None | UndefinedType = Undefined, + granularity_per_source: bool | None | UndefinedType = Undefined, + poll_interval: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TriggerOnCounters. + + + Subclass of AvdModel. + + Args: + condition: Set the logical expression to evaluate. + granularity_per_source: + Set the granularity of event counting for a wildcarded condition. + Example - + condition ( + Arad*.IptCrcErrCnt.delta > 100 ) and ( Arad*.UcFifoFullDrop.delta > 100 ) + [* wildcard is used + here] + poll_interval: Set the polling interval in seconds. + _custom_data: _custom_data + + """ + + class TriggerOnLogging(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"poll_interval": {"type": int}, "regex": {"type": str}, "_custom_data": {"type": dict}} + poll_interval: int | None + """Set the polling interval in seconds.""" + regex: str | None + """Regular expression to use for searching log messages.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + poll_interval: int | None | UndefinedType = Undefined, + regex: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TriggerOnLogging. + + + Subclass of AvdModel. + + Args: + poll_interval: Set the polling interval in seconds. + regex: Regular expression to use for searching log messages. + _custom_data: _custom_data + + """ + + class TriggerOnIntf(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "interface": {"type": str}, + "ip": {"type": bool}, + "ipv6": {"type": bool}, + "operstatus": {"type": bool}, + "_custom_data": {"type": dict}, + } + interface: str + """ + Interface name. + Example - Ethernet4 + Loopback4-6 + Port-channel4,7 + """ + ip: bool | None + """Action is triggered upon changes to interface IP address assignment.""" + ipv6: bool | None + """Action is triggered upon changes to interface ipv6 address assignment.""" + operstatus: bool | None + """Action is triggered upon changes to interface operStatus.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interface: str | UndefinedType = Undefined, + ip: bool | None | UndefinedType = Undefined, + ipv6: bool | None | UndefinedType = Undefined, + operstatus: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TriggerOnIntf. + + + Subclass of AvdModel. + + Args: + interface: + Interface name. + Example - Ethernet4 + Loopback4-6 + Port-channel4,7 + ip: Action is triggered upon changes to interface IP address assignment. + ipv6: Action is triggered upon changes to interface ipv6 address assignment. + operstatus: Action is triggered upon changes to interface operStatus. + _custom_data: _custom_data + + """ + + class TriggerOnMaintenance(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "operation": {"type": str}, + "bgp_peer": {"type": str}, + "action": {"type": str}, + "stage": {"type": str}, + "vrf": {"type": str}, + "interface": {"type": str}, + "unit": {"type": str}, + "_custom_data": {"type": dict}, + } + operation: Literal["enter", "exit"] + bgp_peer: str | None + """ + Ipv4/Ipv6 address or peer group name. + Trigger condition occurs on maintenance operation of specified + BGP peer. + """ + action: Literal["after", "before", "all", "begin", "end"] + """Action for maintenance operation.""" + stage: Literal["bgp", "linkdown", "mlag", "ratemon"] | None + """Action is triggered after/before specified stage.""" + vrf: str | None + """VRF name. VRF can be defined for "bgp_peer" only.""" + interface: str | None + """Trigger condition occurs on maintenance operation of specified interface.""" + unit: str | None + """Name of unit. Trigger condition occurs on maintenance operation of specified unit""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + operation: Literal["enter", "exit"] | UndefinedType = Undefined, + bgp_peer: str | None | UndefinedType = Undefined, + action: Literal["after", "before", "all", "begin", "end"] | UndefinedType = Undefined, + stage: Literal["bgp", "linkdown", "mlag", "ratemon"] | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + interface: str | None | UndefinedType = Undefined, + unit: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TriggerOnMaintenance. + + + Subclass of AvdModel. + + Args: + operation: operation + bgp_peer: + Ipv4/Ipv6 address or peer group name. + Trigger condition occurs on maintenance operation of specified + BGP peer. + action: Action for maintenance operation. + stage: Action is triggered after/before specified stage. + vrf: VRF name. VRF can be defined for "bgp_peer" only. + interface: Trigger condition occurs on maintenance operation of specified interface. + unit: Name of unit. Trigger condition occurs on maintenance operation of specified unit + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "actions": {"type": Actions}, + "delay": {"type": int}, + "trigger": {"type": str}, + "trigger_on_counters": {"type": TriggerOnCounters}, + "trigger_on_logging": {"type": TriggerOnLogging}, + "trigger_on_intf": {"type": TriggerOnIntf}, + "trigger_on_maintenance": {"type": TriggerOnMaintenance}, + "asynchronous": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + name: str + """Event Handler Name.""" + actions: Actions + """ + Note: `bash_command` and `log` are mutually exclusive. `bash_command` takes precedence over `log`. + Subclass of AvdModel. + """ + delay: int | None + """Event-handler delay in seconds.""" + trigger: Literal["on-boot", "on-counters", "on-intf", "on-logging", "on-maintenance", "on-startup-config", "vm-tracer vm"] | None + """Configure event trigger condition.""" + trigger_on_counters: TriggerOnCounters + """Subclass of AvdModel.""" + trigger_on_logging: TriggerOnLogging + """Subclass of AvdModel.""" + trigger_on_intf: TriggerOnIntf + """ + Trigger condition occurs on specified interface changes. + Note: Any one of the `ip`, `ipv6` and + `operstatus` key needs to be defined along with the `interface`. + + Subclass of AvdModel. + """ + trigger_on_maintenance: TriggerOnMaintenance + """ + Settings required for trigger 'on-maintenance'. + + Subclass of AvdModel. + """ + asynchronous: bool + """ + Set the action to be non-blocking. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + actions: Actions | UndefinedType = Undefined, + delay: int | None | UndefinedType = Undefined, + trigger: Literal["on-boot", "on-counters", "on-intf", "on-logging", "on-maintenance", "on-startup-config", "vm-tracer vm"] + | None + | UndefinedType = Undefined, + trigger_on_counters: TriggerOnCounters | UndefinedType = Undefined, + trigger_on_logging: TriggerOnLogging | UndefinedType = Undefined, + trigger_on_intf: TriggerOnIntf | UndefinedType = Undefined, + trigger_on_maintenance: TriggerOnMaintenance | UndefinedType = Undefined, + asynchronous: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EventHandlersItem. + + + Subclass of AvdModel. + + Args: + name: Event Handler Name. + actions: + Note: `bash_command` and `log` are mutually exclusive. `bash_command` takes precedence over `log`. + Subclass of AvdModel. + delay: Event-handler delay in seconds. + trigger: Configure event trigger condition. + trigger_on_counters: Subclass of AvdModel. + trigger_on_logging: Subclass of AvdModel. + trigger_on_intf: + Trigger condition occurs on specified interface changes. + Note: Any one of the `ip`, `ipv6` and + `operstatus` key needs to be defined along with the `interface`. + + Subclass of AvdModel. + trigger_on_maintenance: + Settings required for trigger 'on-maintenance'. + + Subclass of AvdModel. + asynchronous: Set the action to be non-blocking. + _custom_data: _custom_data + + """ + + class EventHandlers(AvdIndexedList[str, EventHandlersItem]): + """Subclass of AvdIndexedList with `EventHandlersItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + EventHandlers._item_type = EventHandlersItem + + class EventMonitor(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, enabled: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + EventMonitor. + + + Subclass of AvdModel. + + Args: + enabled: enabled + _custom_data: _custom_data + + """ + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + class Sampled(AvdModel): + """Subclass of AvdModel.""" + + class Encapsulation(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4_ipv6": {"type": bool}, "mpls": {"type": bool}, "_custom_data": {"type": dict}} + ipv4_ipv6: bool | None + mpls: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4_ipv6: bool | None | UndefinedType = Undefined, + mpls: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Encapsulation. + + + Subclass of AvdModel. + + Args: + ipv4_ipv6: ipv4_ipv6 + mpls: mpls + _custom_data: _custom_data + + """ + + class HardwareOffload(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4": {"type": bool}, "ipv6": {"type": bool}, "threshold_minimum": {"type": int}, "_custom_data": {"type": dict}} + ipv4: bool | None + """Configure hardware offload for IPv4 traffic.""" + ipv6: bool | None + """Configure hardware offload for IPv6 traffic.""" + threshold_minimum: int | None + """Minimum number of samples.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4: bool | None | UndefinedType = Undefined, + ipv6: bool | None | UndefinedType = Undefined, + threshold_minimum: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + HardwareOffload. + + + Subclass of AvdModel. + + Args: + ipv4: Configure hardware offload for IPv4 traffic. + ipv6: Configure hardware offload for IPv6 traffic. + threshold_minimum: Minimum number of samples. + _custom_data: _custom_data + + """ + + class TrackersItem(AvdModel): + """Subclass of AvdModel.""" + + class RecordExport(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "mpls": {"type": bool}, + "on_inactive_timeout": {"type": int}, + "on_interval": {"type": int}, + "_custom_data": {"type": dict}, + } + mpls: bool | None + """Export MPLS forwarding information.""" + on_inactive_timeout: int | None + """Flow record inactive export timeout in milliseconds.""" + on_interval: int | None + """Flow record export interval in milliseconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mpls: bool | None | UndefinedType = Undefined, + on_inactive_timeout: int | None | UndefinedType = Undefined, + on_interval: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RecordExport. + + + Subclass of AvdModel. + + Args: + mpls: Export MPLS forwarding information. + on_inactive_timeout: Flow record inactive export timeout in milliseconds. + on_interval: Flow record export interval in milliseconds. + _custom_data: _custom_data + + """ + + class ExportersItem(AvdModel): + """Subclass of AvdModel.""" + + class Collector(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"host": {"type": str}, "port": {"type": int}, "_custom_data": {"type": dict}} + host: str | None + """Collector IPv4 address or IPv6 address or fully qualified domain name.""" + port: int | None + """Collector Port Number.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + host: str | None | UndefinedType = Undefined, + port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Collector. + + + Subclass of AvdModel. + + Args: + host: Collector IPv4 address or IPv6 address or fully qualified domain name. + port: Collector Port Number. + _custom_data: _custom_data + + """ + + class Format(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipfix_version": {"type": int}, "_custom_data": {"type": dict}} + ipfix_version: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, ipfix_version: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Format. + + + Subclass of AvdModel. + + Args: + ipfix_version: ipfix_version + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "collector": {"type": Collector}, + "format": {"type": Format}, + "local_interface": {"type": str}, + "template_interval": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str + """Exporter Name.""" + collector: Collector + """Subclass of AvdModel.""" + format: Format + """Subclass of AvdModel.""" + local_interface: str | None + """Local Source Interface.""" + template_interval: int | None + """Template interval in milliseconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + collector: Collector | UndefinedType = Undefined, + format: Format | UndefinedType = Undefined, + local_interface: str | None | UndefinedType = Undefined, + template_interval: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ExportersItem. + + + Subclass of AvdModel. + + Args: + name: Exporter Name. + collector: Subclass of AvdModel. + format: Subclass of AvdModel. + local_interface: Local Source Interface. + template_interval: Template interval in milliseconds. + _custom_data: _custom_data + + """ + + class Exporters(AvdIndexedList[str, ExportersItem]): + """Subclass of AvdIndexedList with `ExportersItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Exporters._item_type = ExportersItem + + _fields: ClassVar[dict] = { + "table_size": {"type": int}, + "record_export": {"type": RecordExport}, + "name": {"type": str}, + "exporters": {"type": Exporters}, + "_custom_data": {"type": dict}, + } + table_size: int | None + """Maximum number of entries in flow table.""" + record_export: RecordExport + """Subclass of AvdModel.""" + name: str + """Tracker Name.""" + exporters: Exporters + """Subclass of AvdIndexedList with `ExportersItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + table_size: int | None | UndefinedType = Undefined, + record_export: RecordExport | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + exporters: Exporters | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TrackersItem. + + + Subclass of AvdModel. + + Args: + table_size: Maximum number of entries in flow table. + record_export: Subclass of AvdModel. + name: Tracker Name. + exporters: Subclass of AvdIndexedList with `ExportersItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class Trackers(AvdIndexedList[str, TrackersItem]): + """Subclass of AvdIndexedList with `TrackersItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Trackers._item_type = TrackersItem + + _fields: ClassVar[dict] = { + "encapsulation": {"type": Encapsulation}, + "sample": {"type": int}, + "hardware_offload": {"type": HardwareOffload}, + "trackers": {"type": Trackers}, + "shutdown": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + encapsulation: Encapsulation + """Subclass of AvdModel.""" + sample: int | None + hardware_offload: HardwareOffload + """Subclass of AvdModel.""" + trackers: Trackers + """Subclass of AvdIndexedList with `TrackersItem` items. Primary key is `name` (`str`).""" + shutdown: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + encapsulation: Encapsulation | UndefinedType = Undefined, + sample: int | None | UndefinedType = Undefined, + hardware_offload: HardwareOffload | UndefinedType = Undefined, + trackers: Trackers | UndefinedType = Undefined, + shutdown: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Sampled. + + + Subclass of AvdModel. + + Args: + encapsulation: Subclass of AvdModel. + sample: sample + hardware_offload: Subclass of AvdModel. + trackers: Subclass of AvdIndexedList with `TrackersItem` items. Primary key is `name` (`str`). + shutdown: shutdown + _custom_data: _custom_data + + """ + + class Hardware(AvdModel): + """Subclass of AvdModel.""" + + class Record(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"format_ipfix_standard_timestamps_counters": {"type": bool}, "_custom_data": {"type": dict}} + format_ipfix_standard_timestamps_counters: bool | None + """Enable software export of IPFIX data records.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + format_ipfix_standard_timestamps_counters: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Record. + + + Subclass of AvdModel. + + Args: + format_ipfix_standard_timestamps_counters: Enable software export of IPFIX data records. + _custom_data: _custom_data + + """ + + class TrackersItem(AvdModel): + """Subclass of AvdModel.""" + + class RecordExport(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"on_inactive_timeout": {"type": int}, "on_interval": {"type": int}, "_custom_data": {"type": dict}} + on_inactive_timeout: int | None + """Flow record inactive export timeout in milliseconds.""" + on_interval: int | None + """Flow record export interval in milliseconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + on_inactive_timeout: int | None | UndefinedType = Undefined, + on_interval: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RecordExport. + + + Subclass of AvdModel. + + Args: + on_inactive_timeout: Flow record inactive export timeout in milliseconds. + on_interval: Flow record export interval in milliseconds. + _custom_data: _custom_data + + """ + + class ExportersItem(AvdModel): + """Subclass of AvdModel.""" + + class Collector(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"host": {"type": str}, "port": {"type": int}, "_custom_data": {"type": dict}} + host: str | None + """Collector IPv4 address or IPv6 address or fully qualified domain name.""" + port: int | None + """Collector Port Number.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + host: str | None | UndefinedType = Undefined, + port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Collector. + + + Subclass of AvdModel. + + Args: + host: Collector IPv4 address or IPv6 address or fully qualified domain name. + port: Collector Port Number. + _custom_data: _custom_data + + """ + + class Format(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipfix_version": {"type": int}, "_custom_data": {"type": dict}} + ipfix_version: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, ipfix_version: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Format. + + + Subclass of AvdModel. + + Args: + ipfix_version: ipfix_version + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "collector": {"type": Collector}, + "format": {"type": Format}, + "local_interface": {"type": str}, + "template_interval": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str + """Exporter Name.""" + collector: Collector + """Subclass of AvdModel.""" + format: Format + """Subclass of AvdModel.""" + local_interface: str | None + """Local Source Interface.""" + template_interval: int | None + """Template interval in milliseconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + collector: Collector | UndefinedType = Undefined, + format: Format | UndefinedType = Undefined, + local_interface: str | None | UndefinedType = Undefined, + template_interval: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ExportersItem. + + + Subclass of AvdModel. + + Args: + name: Exporter Name. + collector: Subclass of AvdModel. + format: Subclass of AvdModel. + local_interface: Local Source Interface. + template_interval: Template interval in milliseconds. + _custom_data: _custom_data + + """ + + class Exporters(AvdIndexedList[str, ExportersItem]): + """Subclass of AvdIndexedList with `ExportersItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Exporters._item_type = ExportersItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "record_export": {"type": RecordExport}, + "exporters": {"type": Exporters}, + "_custom_data": {"type": dict}, + } + name: str + """Tracker Name.""" + record_export: RecordExport + """Subclass of AvdModel.""" + exporters: Exporters + """Subclass of AvdIndexedList with `ExportersItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + record_export: RecordExport | UndefinedType = Undefined, + exporters: Exporters | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TrackersItem. + + + Subclass of AvdModel. + + Args: + name: Tracker Name. + record_export: Subclass of AvdModel. + exporters: Subclass of AvdIndexedList with `ExportersItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class Trackers(AvdIndexedList[str, TrackersItem]): + """Subclass of AvdIndexedList with `TrackersItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Trackers._item_type = TrackersItem + + _fields: ClassVar[dict] = { + "record": {"type": Record}, + "trackers": {"type": Trackers}, + "shutdown": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + record: Record + """Subclass of AvdModel.""" + trackers: Trackers + """Subclass of AvdIndexedList with `TrackersItem` items. Primary key is `name` (`str`).""" + shutdown: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + record: Record | UndefinedType = Undefined, + trackers: Trackers | UndefinedType = Undefined, + shutdown: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Hardware. + + + Subclass of AvdModel. + + Args: + record: Subclass of AvdModel. + trackers: Subclass of AvdIndexedList with `TrackersItem` items. Primary key is `name` (`str`). + shutdown: shutdown + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"sampled": {"type": Sampled}, "hardware": {"type": Hardware}, "_custom_data": {"type": dict}} + sampled: Sampled + """Subclass of AvdModel.""" + hardware: Hardware + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sampled: Sampled | UndefinedType = Undefined, + hardware: Hardware | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + sampled: Subclass of AvdModel. + hardware: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Hardware(AvdModel): + """Subclass of AvdModel.""" + + class AccessList(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"mechanism": {"type": str}, "_custom_data": {"type": dict}} + mechanism: Literal["algomatch", "none", "tcam"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mechanism: Literal["algomatch", "none", "tcam"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AccessList. + + + Subclass of AvdModel. + + Args: + mechanism: mechanism + _custom_data: _custom_data + + """ + + class SpeedGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"speed_group": {"type": str}, "serdes": {"type": str}, "_custom_data": {"type": dict}} + speed_group: str + serdes: str | None + """Serdes speed like "10g" or "25g".""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + speed_group: str | UndefinedType = Undefined, + serdes: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SpeedGroupsItem. + + + Subclass of AvdModel. + + Args: + speed_group: speed_group + serdes: Serdes speed like "10g" or "25g". + _custom_data: _custom_data + + """ + + class SpeedGroups(AvdIndexedList[str, SpeedGroupsItem]): + """Subclass of AvdIndexedList with `SpeedGroupsItem` items. Primary key is `speed_group` (`str`).""" + + _primary_key: ClassVar[str] = "speed_group" + + SpeedGroups._item_type = SpeedGroupsItem + + class PortGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"port_group": {"type": str}, "select": {"type": str}, "_custom_data": {"type": dict}} + port_group: str + select: str | None + """Select Ports to activate""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + port_group: str | UndefinedType = Undefined, + select: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PortGroupsItem. + + + Subclass of AvdModel. + + Args: + port_group: port_group + select: Select Ports to activate + _custom_data: _custom_data + + """ + + class PortGroups(AvdIndexedList[str, PortGroupsItem]): + """Subclass of AvdIndexedList with `PortGroupsItem` items. Primary key is `port_group` (`str`).""" + + _primary_key: ClassVar[str] = "port_group" + + PortGroups._item_type = PortGroupsItem + + _fields: ClassVar[dict] = { + "access_list": {"type": AccessList}, + "speed_groups": {"type": SpeedGroups}, + "port_groups": {"type": PortGroups}, + "_custom_data": {"type": dict}, + } + access_list: AccessList + """Subclass of AvdModel.""" + speed_groups: SpeedGroups + """Subclass of AvdIndexedList with `SpeedGroupsItem` items. Primary key is `speed_group` (`str`).""" + port_groups: PortGroups + """Subclass of AvdIndexedList with `PortGroupsItem` items. Primary key is `port_group` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + access_list: AccessList | UndefinedType = Undefined, + speed_groups: SpeedGroups | UndefinedType = Undefined, + port_groups: PortGroups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Hardware. + + + Subclass of AvdModel. + + Args: + access_list: Subclass of AvdModel. + speed_groups: Subclass of AvdIndexedList with `SpeedGroupsItem` items. Primary key is `speed_group` (`str`). + port_groups: Subclass of AvdIndexedList with `PortGroupsItem` items. Primary key is `port_group` (`str`). + _custom_data: _custom_data + + """ + + class HardwareCounters(AvdModel): + """Subclass of AvdModel.""" + + class FeaturesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "direction": {"type": str}, + "address_type": {"type": str}, + "layer3": {"type": bool}, + "vrf": {"type": str}, + "prefix": {"type": str}, + "units_packets": {"type": bool}, + "_custom_data": {"type": dict}, + } + name: Literal[ + "acl", + "decap-group", + "directflow", + "ecn", + "flow-spec", + "gre tunnel interface", + "ip", + "mpls interface", + "mpls lfib", + "mpls tunnel", + "multicast", + "nexthop", + "pbr", + "pdp", + "policing interface", + "qos", + "qos dual-rate-policer", + "route", + "routed-port", + "segment-security", + "subinterface", + "tapagg", + "traffic-class", + "traffic-policy", + "vlan", + "vlan-interface", + "vni decap", + "vni encap", + "vtep decap", + "vtep encap", + ] + direction: Literal["in", "out", "cpu"] | None + """ + Most features support only 'in' and 'out'. Some like traffic-policy support 'cpu'. + Some features DO + NOT have any direction. + This validation IS NOT made by the schemas. + """ + address_type: Literal["ipv4", "ipv6", "mac"] | None + """ + Supported only for the following features: + - acl: [ipv4, ipv6, mac] if direction is 'out' + - + multicast: [ipv4, ipv6] + - route: [ipv4, ipv6] + This validation IS NOT made by the schemas. + """ + layer3: bool | None + """Supported only for the 'ip' feature.""" + vrf: str | None + """ + Supported only for the 'route' feature. + This validation IS NOT made by the schemas. + """ + prefix: str | None + """ + Supported only for the 'route' feature. + Mandatory for the 'route' feature. + This validation IS NOT + made by the schemas. + """ + units_packets: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: Literal[ + "acl", + "decap-group", + "directflow", + "ecn", + "flow-spec", + "gre tunnel interface", + "ip", + "mpls interface", + "mpls lfib", + "mpls tunnel", + "multicast", + "nexthop", + "pbr", + "pdp", + "policing interface", + "qos", + "qos dual-rate-policer", + "route", + "routed-port", + "segment-security", + "subinterface", + "tapagg", + "traffic-class", + "traffic-policy", + "vlan", + "vlan-interface", + "vni decap", + "vni encap", + "vtep decap", + "vtep encap", + ] + | UndefinedType = Undefined, + direction: Literal["in", "out", "cpu"] | None | UndefinedType = Undefined, + address_type: Literal["ipv4", "ipv6", "mac"] | None | UndefinedType = Undefined, + layer3: bool | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + prefix: str | None | UndefinedType = Undefined, + units_packets: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FeaturesItem. + + + Subclass of AvdModel. + + Args: + name: name + direction: + Most features support only 'in' and 'out'. Some like traffic-policy support 'cpu'. + Some features DO + NOT have any direction. + This validation IS NOT made by the schemas. + address_type: + Supported only for the following features: + - acl: [ipv4, ipv6, mac] if direction is 'out' + - + multicast: [ipv4, ipv6] + - route: [ipv4, ipv6] + This validation IS NOT made by the schemas. + layer3: Supported only for the 'ip' feature. + vrf: + Supported only for the 'route' feature. + This validation IS NOT made by the schemas. + prefix: + Supported only for the 'route' feature. + Mandatory for the 'route' feature. + This validation IS NOT + made by the schemas. + units_packets: units_packets + _custom_data: _custom_data + + """ + + class Features(AvdList[FeaturesItem]): + """Subclass of AvdList with `FeaturesItem` items.""" + + Features._item_type = FeaturesItem + + _fields: ClassVar[dict] = {"features": {"type": Features}, "_custom_data": {"type": dict}} + features: Features + """ + This data model allows to configure the list of hardware counters feature + available on Arista + platforms. + + The `name` key accepts a list of valid_values which MUST be updated to support + new + feature as they are released in EOS. + + The available values of the different keys like 'direction' or + 'address_type' + are feature and hardware dependent and this model DOES NOT validate that the + combinations are valid. It is the responsibility of the user of this data model + to make sure that + the rendered CLI is accepted by the targeted device. + + Examples: + + * Use: + ```yaml + hardware_counters: + features: + - name: ip + direction: out + layer3: + true + units_packets: true + ``` + + to render: + ```eos + hardware counter feature + ip out layer3 units packets + ``` + * Use: + ```yaml + hardware_counters: + features: + - name: route + address_type: ipv4 + vrf: test + prefix: 192.168.0.0/24 + ``` + + to render: + ```eos + hardware counter feature route ipv4 vrf test 192.168.0.0/24 + ``` + + + Subclass of AvdList with `FeaturesItem` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, features: Features | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + HardwareCounters. + + + Subclass of AvdModel. + + Args: + features: + This data model allows to configure the list of hardware counters feature + available on Arista + platforms. + + The `name` key accepts a list of valid_values which MUST be updated to support + new + feature as they are released in EOS. + + The available values of the different keys like 'direction' or + 'address_type' + are feature and hardware dependent and this model DOES NOT validate that the + combinations are valid. It is the responsibility of the user of this data model + to make sure that + the rendered CLI is accepted by the targeted device. + + Examples: # fmt: skip + + * Use: + ```yaml + hardware_counters: + features: + - name: ip + direction: out + layer3: + true + units_packets: true + ``` + + to render: + ```eos + hardware counter feature + ip out layer3 units packets + ``` + * Use: + ```yaml + hardware_counters: + features: + - name: route + address_type: ipv4 + vrf: test + prefix: 192.168.0.0/24 + ``` + + to render: + ```eos + hardware counter feature route ipv4 vrf test 192.168.0.0/24 + ``` + + + Subclass of AvdList with `FeaturesItem` items. + _custom_data: _custom_data + + """ + + class InterfaceDefaults(AvdModel): + """Subclass of AvdModel.""" + + class Ethernet(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"shutdown": {"type": bool}, "_custom_data": {"type": dict}} + shutdown: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, shutdown: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Ethernet. + + + Subclass of AvdModel. + + Args: + shutdown: shutdown + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ethernet": {"type": Ethernet}, "mtu": {"type": int}, "_custom_data": {"type": dict}} + ethernet: Ethernet + """Subclass of AvdModel.""" + mtu: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ethernet: Ethernet | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + InterfaceDefaults. + + + Subclass of AvdModel. + + Args: + ethernet: Subclass of AvdModel. + mtu: mtu + _custom_data: _custom_data + + """ + + class InterfaceGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class Interfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Interfaces._item_type = str + + class BgpMaintenanceProfiles(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + BgpMaintenanceProfiles._item_type = str + + class InterfaceMaintenanceProfiles(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + InterfaceMaintenanceProfiles._item_type = str + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "interfaces": {"type": Interfaces}, + "bgp_maintenance_profiles": {"type": BgpMaintenanceProfiles}, + "interface_maintenance_profiles": {"type": InterfaceMaintenanceProfiles}, + "_custom_data": {"type": dict}, + } + name: str + """Interface-Group name.""" + interfaces: Interfaces + """Subclass of AvdList with `str` items.""" + bgp_maintenance_profiles: BgpMaintenanceProfiles + """Subclass of AvdList with `str` items.""" + interface_maintenance_profiles: InterfaceMaintenanceProfiles + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + interfaces: Interfaces | UndefinedType = Undefined, + bgp_maintenance_profiles: BgpMaintenanceProfiles | UndefinedType = Undefined, + interface_maintenance_profiles: InterfaceMaintenanceProfiles | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + InterfaceGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Interface-Group name. + interfaces: Subclass of AvdList with `str` items. + bgp_maintenance_profiles: Subclass of AvdList with `str` items. + interface_maintenance_profiles: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class InterfaceGroups(AvdIndexedList[str, InterfaceGroupsItem]): + """Subclass of AvdIndexedList with `InterfaceGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + InterfaceGroups._item_type = InterfaceGroupsItem + + class InterfaceProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class Commands(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Commands._item_type = str + + _fields: ClassVar[dict] = {"name": {"type": str}, "commands": {"type": Commands}, "_custom_data": {"type": dict}} + name: str + """Interface-Profile Name.""" + commands: Commands + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + commands: Commands | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + InterfaceProfilesItem. + + + Subclass of AvdModel. + + Args: + name: Interface-Profile Name. + commands: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class InterfaceProfiles(AvdIndexedList[str, InterfaceProfilesItem]): + """Subclass of AvdIndexedList with `InterfaceProfilesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + InterfaceProfiles._item_type = InterfaceProfilesItem + + class IpAccessListsItem(AvdModel): + """Subclass of AvdModel.""" + + class EntriesItem(AvdModel): + """Subclass of AvdModel.""" + + class SourcePorts(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + SourcePorts._item_type = str + + class DestinationPorts(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DestinationPorts._item_type = str + + class TcpFlags(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + TcpFlags._item_type = str + + _fields: ClassVar[dict] = { + "sequence": {"type": int}, + "remark": {"type": str}, + "action": {"type": str}, + "protocol": {"type": str}, + "source": {"type": str}, + "source_ports_match": {"type": str, "default": "eq"}, + "source_ports": {"type": SourcePorts}, + "destination": {"type": str}, + "destination_ports_match": {"type": str, "default": "eq"}, + "destination_ports": {"type": DestinationPorts}, + "tcp_flags": {"type": TcpFlags}, + "fragments": {"type": bool}, + "log": {"type": bool}, + "ttl": {"type": int}, + "ttl_match": {"type": str, "default": "eq"}, + "icmp_type": {"type": str}, + "icmp_code": {"type": str}, + "nexthop_group": {"type": str}, + "tracked": {"type": bool}, + "dscp": {"type": str}, + "vlan_number": {"type": int}, + "vlan_inner": {"type": bool, "default": False}, + "vlan_mask": {"type": str}, + "_custom_data": {"type": dict}, + } + sequence: int | None + """ACL entry sequence number.""" + remark: str | None + """ + Comment up to 100 characters. + If remark is defined, other keys in the ACL entry will be ignored. + """ + action: Literal["permit", "deny"] | None + """ + ACL action. + Required except for remarks. + """ + protocol: str | None + """ + "ip", "tcp", "udp", "icmp" or other protocol name or number. + Required except for remarks. + """ + source: str | None + """ + "any", "/" or "". + "" without a mask means host. + Required except for remarks. + """ + source_ports_match: Literal["eq", "gt", "lt", "neq", "range"] + """Default value: `"eq"`""" + source_ports: SourcePorts + """Subclass of AvdList with `str` items.""" + destination: str | None + """ + "any", "/" or "". + "" without a mask means host. + Required except for remarks. + """ + destination_ports_match: Literal["eq", "gt", "lt", "neq", "range"] + """Default value: `"eq"`""" + destination_ports: DestinationPorts + """Subclass of AvdList with `str` items.""" + tcp_flags: TcpFlags + """Subclass of AvdList with `str` items.""" + fragments: bool | None + """Match non-head fragment packets.""" + log: bool | None + """Log matches against this rule.""" + ttl: int | None + """TTL value.""" + ttl_match: Literal["eq", "gt", "lt", "neq"] + """Default value: `"eq"`""" + icmp_type: str | None + """Message type name/number for ICMP packets.""" + icmp_code: str | None + """Message code for ICMP packets.""" + nexthop_group: str | None + """nexthop-group name.""" + tracked: bool | None + """Match packets in existing ICMP/UDP/TCP connections.""" + dscp: str | None + """DSCP value or name.""" + vlan_number: int | None + vlan_inner: bool + """Default value: `False`""" + vlan_mask: str | None + """0x000-0xFFF VLAN mask.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sequence: int | None | UndefinedType = Undefined, + remark: str | None | UndefinedType = Undefined, + action: Literal["permit", "deny"] | None | UndefinedType = Undefined, + protocol: str | None | UndefinedType = Undefined, + source: str | None | UndefinedType = Undefined, + source_ports_match: Literal["eq", "gt", "lt", "neq", "range"] | UndefinedType = Undefined, + source_ports: SourcePorts | UndefinedType = Undefined, + destination: str | None | UndefinedType = Undefined, + destination_ports_match: Literal["eq", "gt", "lt", "neq", "range"] | UndefinedType = Undefined, + destination_ports: DestinationPorts | UndefinedType = Undefined, + tcp_flags: TcpFlags | UndefinedType = Undefined, + fragments: bool | None | UndefinedType = Undefined, + log: bool | None | UndefinedType = Undefined, + ttl: int | None | UndefinedType = Undefined, + ttl_match: Literal["eq", "gt", "lt", "neq"] | UndefinedType = Undefined, + icmp_type: str | None | UndefinedType = Undefined, + icmp_code: str | None | UndefinedType = Undefined, + nexthop_group: str | None | UndefinedType = Undefined, + tracked: bool | None | UndefinedType = Undefined, + dscp: str | None | UndefinedType = Undefined, + vlan_number: int | None | UndefinedType = Undefined, + vlan_inner: bool | UndefinedType = Undefined, + vlan_mask: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EntriesItem. + + + Subclass of AvdModel. + + Args: + sequence: ACL entry sequence number. + remark: + Comment up to 100 characters. + If remark is defined, other keys in the ACL entry will be ignored. + action: + ACL action. + Required except for remarks. + protocol: + "ip", "tcp", "udp", "icmp" or other protocol name or number. + Required except for remarks. + source: + "any", "/" or "". + "" without a mask means host. + Required except for remarks. + source_ports_match: source_ports_match + source_ports: Subclass of AvdList with `str` items. + destination: + "any", "/" or "". + "" without a mask means host. + Required except for remarks. + destination_ports_match: destination_ports_match + destination_ports: Subclass of AvdList with `str` items. + tcp_flags: Subclass of AvdList with `str` items. + fragments: Match non-head fragment packets. + log: Log matches against this rule. + ttl: TTL value. + ttl_match: ttl_match + icmp_type: Message type name/number for ICMP packets. + icmp_code: Message code for ICMP packets. + nexthop_group: nexthop-group name. + tracked: Match packets in existing ICMP/UDP/TCP connections. + dscp: DSCP value or name. + vlan_number: vlan_number + vlan_inner: vlan_inner + vlan_mask: 0x000-0xFFF VLAN mask. + _custom_data: _custom_data + + """ + + class Entries(AvdList[EntriesItem]): + """Subclass of AvdList with `EntriesItem` items.""" + + Entries._item_type = EntriesItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "counters_per_entry": {"type": bool}, + "entries": {"type": Entries}, + "permit_response_traffic": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Access-list Name.""" + counters_per_entry: bool | None + entries: Entries + """ + ACL Entries. + + Subclass of AvdList with `EntriesItem` items. + """ + permit_response_traffic: Literal["nat"] | None + """ + Permit response traffic automatically based on NAT translations. + Minimum EOS version requirement + 4.32.2F. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + counters_per_entry: bool | None | UndefinedType = Undefined, + entries: Entries | UndefinedType = Undefined, + permit_response_traffic: Literal["nat"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpAccessListsItem. + + + Subclass of AvdModel. + + Args: + name: Access-list Name. + counters_per_entry: counters_per_entry + entries: + ACL Entries. + + Subclass of AvdList with `EntriesItem` items. + permit_response_traffic: + Permit response traffic automatically based on NAT translations. + Minimum EOS version requirement + 4.32.2F. + _custom_data: _custom_data + + """ + + class IpAccessLists(AvdIndexedList[str, IpAccessListsItem]): + """Subclass of AvdIndexedList with `IpAccessListsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + IpAccessLists._item_type = IpAccessListsItem + + class IpCommunityListsItem(AvdModel): + """Subclass of AvdModel.""" + + class EntriesItem(AvdModel): + """Subclass of AvdModel.""" + + class Communities(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Communities._item_type = str + + _fields: ClassVar[dict] = {"action": {"type": str}, "communities": {"type": Communities}, "regexp": {"type": str}, "_custom_data": {"type": dict}} + action: Literal["permit", "deny"] + communities: Communities + """ + If defined, a standard community-list will be configured. + Supported community strings (case + insensitive): + - GSHUT + - internet + - local-as + - no-advertise + - no-export + - <1-4294967040> + - aa:nn + Subclass of AvdList with `str` items. + """ + regexp: str | None + """ + Regular Expression. + If defined, a regex community-list will be configured. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["permit", "deny"] | UndefinedType = Undefined, + communities: Communities | UndefinedType = Undefined, + regexp: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EntriesItem. + + + Subclass of AvdModel. + + Args: + action: action + communities: + If defined, a standard community-list will be configured. + Supported community strings (case + insensitive): + - GSHUT + - internet + - local-as + - no-advertise + - no-export + - <1-4294967040> + - aa:nn + Subclass of AvdList with `str` items. + regexp: + Regular Expression. + If defined, a regex community-list will be configured. + _custom_data: _custom_data + + """ + + class Entries(AvdList[EntriesItem]): + """Subclass of AvdList with `EntriesItem` items.""" + + Entries._item_type = EntriesItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "entries": {"type": Entries}, "_custom_data": {"type": dict}} + name: str + """IP Community-list Name.""" + entries: Entries + """Subclass of AvdList with `EntriesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + entries: Entries | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpCommunityListsItem. + + + Subclass of AvdModel. + + Args: + name: IP Community-list Name. + entries: Subclass of AvdList with `EntriesItem` items. + _custom_data: _custom_data + + """ + + class IpCommunityLists(AvdIndexedList[str, IpCommunityListsItem]): + """Subclass of AvdIndexedList with `IpCommunityListsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + IpCommunityLists._item_type = IpCommunityListsItem + + class IpDhcpRelay(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "always_on": {"type": bool}, + "all_subnets": {"type": bool}, + "information_option": {"type": bool}, + "_custom_data": {"type": dict}, + } + always_on: bool | None + """DhcpRelay Agent will be in always-on mode.""" + all_subnets: bool | None + """Allow forwarding requests with secondary IP addresses in the gateway address "giaddr" field.""" + information_option: bool | None + """Insert Option-82 information.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + always_on: bool | None | UndefinedType = Undefined, + all_subnets: bool | None | UndefinedType = Undefined, + information_option: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpDhcpRelay. + + + Subclass of AvdModel. + + Args: + always_on: DhcpRelay Agent will be in always-on mode. + all_subnets: Allow forwarding requests with secondary IP addresses in the gateway address "giaddr" field. + information_option: Insert Option-82 information. + _custom_data: _custom_data + + """ + + class IpDhcpSnooping(AvdModel): + """Subclass of AvdModel.""" + + class InformationOption(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "circuit_id_type": {"type": str}, + "circuit_id_format": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Enable insertion of option-82 in DHCP request packets.""" + circuit_id_type: str | None + """"none" or <0 - 255>.""" + circuit_id_format: Literal["%h:%p", "%p:%v"] | None + """ + Required if `circuit_id_type` is set. + - "%h:%p" Hostname and interface name + - "%p:%v" Interface name + and VLAN ID + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + circuit_id_type: str | None | UndefinedType = Undefined, + circuit_id_format: Literal["%h:%p", "%p:%v"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + InformationOption. + + + Subclass of AvdModel. + + Args: + enabled: Enable insertion of option-82 in DHCP request packets. + circuit_id_type: "none" or <0 - 255>. + circuit_id_format: + Required if `circuit_id_type` is set. + - "%h:%p" Hostname and interface name + - "%p:%v" Interface name + and VLAN ID + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "bridging": {"type": bool}, + "information_option": {"type": InformationOption}, + "vlan": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + bridging: bool | None + information_option: InformationOption + """Subclass of AvdModel.""" + vlan: str | None + """ + VLAN range as string. + "< vlan_id >, < vlan_id >-< vlan_id >" + Example: 15,16,17,18 + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + bridging: bool | None | UndefinedType = Undefined, + information_option: InformationOption | UndefinedType = Undefined, + vlan: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpDhcpSnooping. + + + Subclass of AvdModel. + + Args: + enabled: enabled + bridging: bridging + information_option: Subclass of AvdModel. + vlan: + VLAN range as string. + "< vlan_id >, < vlan_id >-< vlan_id >" + Example: 15,16,17,18 + _custom_data: _custom_data + + """ + + class IpDomainLookup(AvdModel): + """Subclass of AvdModel.""" + + class SourceInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Source Interface.""" + vrf: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SourceInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: Source Interface. + vrf: vrf + _custom_data: _custom_data + + """ + + class SourceInterfaces(AvdIndexedList[str, SourceInterfacesItem]): + """Subclass of AvdIndexedList with `SourceInterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + SourceInterfaces._item_type = SourceInterfacesItem + + _fields: ClassVar[dict] = {"source_interfaces": {"type": SourceInterfaces}, "_custom_data": {"type": dict}} + source_interfaces: SourceInterfaces + """Subclass of AvdIndexedList with `SourceInterfacesItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, source_interfaces: SourceInterfaces | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + IpDomainLookup. + + + Subclass of AvdModel. + + Args: + source_interfaces: Subclass of AvdIndexedList with `SourceInterfacesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class IpExtcommunityListsItem(AvdModel): + """Subclass of AvdModel.""" + + class EntriesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"type": {"type": str}, "extcommunities": {"type": str}, "_custom_data": {"type": dict}} + type: Literal["permit", "deny"] + extcommunities: str + """ + Communities as string. + Example: "65000:65000" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + type: Literal["permit", "deny"] | UndefinedType = Undefined, + extcommunities: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EntriesItem. + + + Subclass of AvdModel. + + Args: + type: type + extcommunities: + Communities as string. + Example: "65000:65000" + _custom_data: _custom_data + + """ + + class Entries(AvdList[EntriesItem]): + """Subclass of AvdList with `EntriesItem` items.""" + + Entries._item_type = EntriesItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "entries": {"type": Entries}, "_custom_data": {"type": dict}} + name: str + """Community-list Name.""" + entries: Entries + """Subclass of AvdList with `EntriesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + entries: Entries | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpExtcommunityListsItem. + + + Subclass of AvdModel. + + Args: + name: Community-list Name. + entries: Subclass of AvdList with `EntriesItem` items. + _custom_data: _custom_data + + """ + + class IpExtcommunityLists(AvdIndexedList[str, IpExtcommunityListsItem]): + """Subclass of AvdIndexedList with `IpExtcommunityListsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + IpExtcommunityLists._item_type = IpExtcommunityListsItem + + class IpExtcommunityListsRegexpItem(AvdModel): + """Subclass of AvdModel.""" + + class EntriesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"type": {"type": str}, "regexp": {"type": str}, "_custom_data": {"type": dict}} + type: Literal["permit", "deny"] + regexp: str + """Regular Expression.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + type: Literal["permit", "deny"] | UndefinedType = Undefined, + regexp: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EntriesItem. + + + Subclass of AvdModel. + + Args: + type: type + regexp: Regular Expression. + _custom_data: _custom_data + + """ + + class Entries(AvdList[EntriesItem]): + """Subclass of AvdList with `EntriesItem` items.""" + + Entries._item_type = EntriesItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "entries": {"type": Entries}, "_custom_data": {"type": dict}} + name: str + """Community-list Name.""" + entries: Entries + """Subclass of AvdList with `EntriesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + entries: Entries | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpExtcommunityListsRegexpItem. + + + Subclass of AvdModel. + + Args: + name: Community-list Name. + entries: Subclass of AvdList with `EntriesItem` items. + _custom_data: _custom_data + + """ + + class IpExtcommunityListsRegexp(AvdIndexedList[str, IpExtcommunityListsRegexpItem]): + """ + Subclass of AvdIndexedList with `IpExtcommunityListsRegexpItem` items. Primary key is `name` + (`str`). + """ + + _primary_key: ClassVar[str] = "name" + + IpExtcommunityListsRegexp._item_type = IpExtcommunityListsRegexpItem + + class IpFtpClientSourceInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Interface Name.""" + vrf: str | None + """VRF Name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpFtpClientSourceInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: Interface Name. + vrf: VRF Name. + _custom_data: _custom_data + + """ + + class IpFtpClientSourceInterfaces(AvdList[IpFtpClientSourceInterfacesItem]): + """Subclass of AvdList with `IpFtpClientSourceInterfacesItem` items.""" + + IpFtpClientSourceInterfaces._item_type = IpFtpClientSourceInterfacesItem + + class IpHardware(AvdModel): + """Subclass of AvdModel.""" + + class Fib(AvdModel): + """Subclass of AvdModel.""" + + class Optimize(AvdModel): + """Subclass of AvdModel.""" + + class Prefixes(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "_custom_data": {"type": dict}} + profile: Literal["internet", "urpf-internet"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: Literal["internet", "urpf-internet"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Prefixes. + + + Subclass of AvdModel. + + Args: + profile: profile + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"prefixes": {"type": Prefixes}, "_custom_data": {"type": dict}} + prefixes: Prefixes + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, prefixes: Prefixes | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Optimize. + + + Subclass of AvdModel. + + Args: + prefixes: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"optimize": {"type": Optimize}, "_custom_data": {"type": dict}} + optimize: Optimize + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, optimize: Optimize | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Fib. + + + Subclass of AvdModel. + + Args: + optimize: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"fib": {"type": Fib}, "_custom_data": {"type": dict}} + fib: Fib + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, fib: Fib | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + IpHardware. + + + Subclass of AvdModel. + + Args: + fib: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class IpHttpClientSourceInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + """Interface Name.""" + vrf: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpHttpClientSourceInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: Interface Name. + vrf: vrf + _custom_data: _custom_data + + """ + + class IpHttpClientSourceInterfaces(AvdList[IpHttpClientSourceInterfacesItem]): + """Subclass of AvdList with `IpHttpClientSourceInterfacesItem` items.""" + + IpHttpClientSourceInterfaces._item_type = IpHttpClientSourceInterfacesItem + + class IpIgmpSnooping(AvdModel): + """Subclass of AvdModel.""" + + class Querier(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "address": {"type": str}, + "query_interval": {"type": int}, + "max_response_time": {"type": int}, + "last_member_query_interval": {"type": int}, + "last_member_query_count": {"type": int}, + "startup_query_interval": {"type": int}, + "startup_query_count": {"type": int}, + "version": {"type": int}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + address: str | None + """IP Address.""" + query_interval: int | None + max_response_time: int | None + last_member_query_interval: int | None + last_member_query_count: int | None + startup_query_interval: int | None + startup_query_count: int | None + version: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + address: str | None | UndefinedType = Undefined, + query_interval: int | None | UndefinedType = Undefined, + max_response_time: int | None | UndefinedType = Undefined, + last_member_query_interval: int | None | UndefinedType = Undefined, + last_member_query_count: int | None | UndefinedType = Undefined, + startup_query_interval: int | None | UndefinedType = Undefined, + startup_query_count: int | None | UndefinedType = Undefined, + version: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Querier. + + + Subclass of AvdModel. + + Args: + enabled: enabled + address: IP Address. + query_interval: query_interval + max_response_time: max_response_time + last_member_query_interval: last_member_query_interval + last_member_query_count: last_member_query_count + startup_query_interval: startup_query_interval + startup_query_count: startup_query_count + version: version + _custom_data: _custom_data + + """ + + class VlansItem(AvdModel): + """Subclass of AvdModel.""" + + class Querier(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "address": {"type": str}, + "query_interval": {"type": int}, + "max_response_time": {"type": int}, + "last_member_query_interval": {"type": int}, + "last_member_query_count": {"type": int}, + "startup_query_interval": {"type": int}, + "startup_query_count": {"type": int}, + "version": {"type": int}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + address: str | None + """IP Address.""" + query_interval: int | None + max_response_time: int | None + last_member_query_interval: int | None + last_member_query_count: int | None + startup_query_interval: int | None + startup_query_count: int | None + version: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + address: str | None | UndefinedType = Undefined, + query_interval: int | None | UndefinedType = Undefined, + max_response_time: int | None | UndefinedType = Undefined, + last_member_query_interval: int | None | UndefinedType = Undefined, + last_member_query_count: int | None | UndefinedType = Undefined, + startup_query_interval: int | None | UndefinedType = Undefined, + startup_query_count: int | None | UndefinedType = Undefined, + version: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Querier. + + + Subclass of AvdModel. + + Args: + enabled: enabled + address: IP Address. + query_interval: query_interval + max_response_time: max_response_time + last_member_query_interval: last_member_query_interval + last_member_query_count: last_member_query_count + startup_query_interval: startup_query_interval + startup_query_count: startup_query_count + version: version + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "enabled": {"type": bool}, + "querier": {"type": Querier}, + "max_groups": {"type": int}, + "fast_leave": {"type": bool}, + "proxy": {"type": bool}, + "_custom_data": {"type": dict}, + } + id: int + """VLAN ID.""" + enabled: bool | None + querier: Querier + """Subclass of AvdModel.""" + max_groups: int | None + fast_leave: bool | None + proxy: bool | None + """Global proxy settings should be enabled before enabling per-vlan.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + enabled: bool | None | UndefinedType = Undefined, + querier: Querier | UndefinedType = Undefined, + max_groups: int | None | UndefinedType = Undefined, + fast_leave: bool | None | UndefinedType = Undefined, + proxy: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VlansItem. + + + Subclass of AvdModel. + + Args: + id: VLAN ID. + enabled: enabled + querier: Subclass of AvdModel. + max_groups: max_groups + fast_leave: fast_leave + proxy: Global proxy settings should be enabled before enabling per-vlan. + _custom_data: _custom_data + + """ + + class Vlans(AvdIndexedList[int, VlansItem]): + """Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + Vlans._item_type = VlansItem + + _fields: ClassVar[dict] = { + "globally_enabled": {"type": bool, "default": True}, + "robustness_variable": {"type": int}, + "restart_query_interval": {"type": int}, + "interface_restart_query": {"type": int}, + "fast_leave": {"type": bool}, + "querier": {"type": Querier}, + "proxy": {"type": bool}, + "vlans": {"type": Vlans}, + "_custom_data": {"type": dict}, + } + globally_enabled: bool + """ + Activate or deactivate IGMP snooping for all vlans where `vlans` allows user to activate / + deactivate IGMP snooping per vlan. + + Default value: `True` + """ + robustness_variable: int | None + restart_query_interval: int | None + interface_restart_query: int | None + fast_leave: bool | None + querier: Querier + """Subclass of AvdModel.""" + proxy: bool | None + vlans: Vlans + """Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + globally_enabled: bool | UndefinedType = Undefined, + robustness_variable: int | None | UndefinedType = Undefined, + restart_query_interval: int | None | UndefinedType = Undefined, + interface_restart_query: int | None | UndefinedType = Undefined, + fast_leave: bool | None | UndefinedType = Undefined, + querier: Querier | UndefinedType = Undefined, + proxy: bool | None | UndefinedType = Undefined, + vlans: Vlans | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpIgmpSnooping. + + + Subclass of AvdModel. + + Args: + globally_enabled: + Activate or deactivate IGMP snooping for all vlans where `vlans` allows user to activate / + deactivate IGMP snooping per vlan. + robustness_variable: robustness_variable + restart_query_interval: restart_query_interval + interface_restart_query: interface_restart_query + fast_leave: fast_leave + querier: Subclass of AvdModel. + proxy: proxy + vlans: Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`int`). + _custom_data: _custom_data + + """ + + class IpNameServersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ip_address": {"type": str}, "vrf": {"type": str}, "priority": {"type": int}, "_custom_data": {"type": dict}} + ip_address: str + """IPv4 or IPv6 address for DNS server.""" + vrf: str | None + """VRF Name.""" + priority: int | None + """Priority value (lower is first).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpNameServersItem. + + + Subclass of AvdModel. + + Args: + ip_address: IPv4 or IPv6 address for DNS server. + vrf: VRF Name. + priority: Priority value (lower is first). + _custom_data: _custom_data + + """ + + class IpNameServers(AvdList[IpNameServersItem]): + """Subclass of AvdList with `IpNameServersItem` items.""" + + IpNameServers._item_type = IpNameServersItem + + class IpNat(AvdModel): + """Subclass of AvdModel.""" + + class ProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class Destination(AvdModel): + """Subclass of AvdModel.""" + + class DynamicItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "access_list": {"type": str}, + "comment": {"type": str}, + "pool_name": {"type": str}, + "priority": {"type": int}, + "_custom_data": {"type": dict}, + } + access_list: str + comment: str | None + pool_name: str + priority: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + access_list: str | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + pool_name: str | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DynamicItem. + + + Subclass of AvdModel. + + Args: + access_list: access_list + comment: comment + pool_name: pool_name + priority: priority + _custom_data: _custom_data + + """ + + class Dynamic(AvdIndexedList[str, DynamicItem]): + """Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`).""" + + _primary_key: ClassVar[str] = "access_list" + + Dynamic._item_type = DynamicItem + + class StaticItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "access_list": {"type": str}, + "comment": {"type": str}, + "direction": {"type": str}, + "group": {"type": int}, + "original_ip": {"type": str}, + "original_port": {"type": int}, + "priority": {"type": int}, + "protocol": {"type": str}, + "translated_ip": {"type": str}, + "translated_port": {"type": int}, + "_custom_data": {"type": dict}, + } + access_list: str | None + """'access_list' and 'group' are mutual exclusive.""" + comment: str | None + direction: Literal["egress", "ingress"] | None + """ + Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware + platform. + EOS might remove this keyword in the configuration. So, check the configuration on + targeted HW/SW. + """ + group: int | None + """'access_list' and 'group' are mutual exclusive.""" + original_ip: str | None + """IPv4 address. The combination of `original_ip` and `original_port` must be unique.""" + original_port: int | None + """TCP/UDP port. The combination of `original_ip` and `original_port` must be unique.""" + priority: int | None + protocol: Literal["udp", "tcp"] | None + translated_ip: str + """IPv4 address.""" + translated_port: int | None + """requires 'original_port'.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + access_list: str | None | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + direction: Literal["egress", "ingress"] | None | UndefinedType = Undefined, + group: int | None | UndefinedType = Undefined, + original_ip: str | None | UndefinedType = Undefined, + original_port: int | None | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + protocol: Literal["udp", "tcp"] | None | UndefinedType = Undefined, + translated_ip: str | UndefinedType = Undefined, + translated_port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StaticItem. + + + Subclass of AvdModel. + + Args: + access_list: 'access_list' and 'group' are mutual exclusive. + comment: comment + direction: + Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware + platform. + EOS might remove this keyword in the configuration. So, check the configuration on + targeted HW/SW. + group: 'access_list' and 'group' are mutual exclusive. + original_ip: IPv4 address. The combination of `original_ip` and `original_port` must be unique. + original_port: TCP/UDP port. The combination of `original_ip` and `original_port` must be unique. + priority: priority + protocol: protocol + translated_ip: IPv4 address. + translated_port: requires 'original_port'. + _custom_data: _custom_data + + """ + + class Static(AvdList[StaticItem]): + """Subclass of AvdList with `StaticItem` items.""" + + Static._item_type = StaticItem + + _fields: ClassVar[dict] = {"dynamic": {"type": Dynamic}, "static": {"type": Static}, "_custom_data": {"type": dict}} + dynamic: Dynamic + """Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`).""" + static: Static + """Subclass of AvdList with `StaticItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dynamic: Dynamic | UndefinedType = Undefined, + static: Static | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Destination. + + + Subclass of AvdModel. + + Args: + dynamic: Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`). + static: Subclass of AvdList with `StaticItem` items. + _custom_data: _custom_data + + """ + + class Source(AvdModel): + """Subclass of AvdModel.""" + + class DynamicItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "access_list": {"type": str}, + "comment": {"type": str}, + "nat_type": {"type": str}, + "pool_name": {"type": str}, + "priority": {"type": int}, + "_custom_data": {"type": dict}, + } + access_list: str + comment: str | None + nat_type: Literal["overload", "pool", "pool-address-only", "pool-full-cone"] + pool_name: str | None + """ + required if 'nat_type' is pool, pool-address-only or pool-full-cone. + ignored if 'nat_type' is + overload. + """ + priority: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + access_list: str | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + nat_type: Literal["overload", "pool", "pool-address-only", "pool-full-cone"] | UndefinedType = Undefined, + pool_name: str | None | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DynamicItem. + + + Subclass of AvdModel. + + Args: + access_list: access_list + comment: comment + nat_type: nat_type + pool_name: + required if 'nat_type' is pool, pool-address-only or pool-full-cone. + ignored if 'nat_type' is + overload. + priority: priority + _custom_data: _custom_data + + """ + + class Dynamic(AvdIndexedList[str, DynamicItem]): + """Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`).""" + + _primary_key: ClassVar[str] = "access_list" + + Dynamic._item_type = DynamicItem + + class StaticItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "access_list": {"type": str}, + "comment": {"type": str}, + "direction": {"type": str}, + "group": {"type": int}, + "original_ip": {"type": str}, + "original_port": {"type": int}, + "priority": {"type": int}, + "protocol": {"type": str}, + "translated_ip": {"type": str}, + "translated_port": {"type": int}, + "_custom_data": {"type": dict}, + } + access_list: str | None + """'access_list' and 'group' are mutual exclusive.""" + comment: str | None + direction: Literal["egress", "ingress"] | None + """ + Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware + platform. + EOS might remove this keyword in the configuration. So, check the configuration on + targeted HW/SW. + """ + group: int | None + """'access_list' and 'group' are mutual exclusive.""" + original_ip: str | None + """IPv4 address. The combination of `original_ip` and `original_port` must be unique.""" + original_port: int | None + """TCP/UDP port. The combination of `original_ip` and `original_port` must be unique.""" + priority: int | None + protocol: Literal["udp", "tcp"] | None + translated_ip: str + """IPv4 address.""" + translated_port: int | None + """requires 'original_port'.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + access_list: str | None | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + direction: Literal["egress", "ingress"] | None | UndefinedType = Undefined, + group: int | None | UndefinedType = Undefined, + original_ip: str | None | UndefinedType = Undefined, + original_port: int | None | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + protocol: Literal["udp", "tcp"] | None | UndefinedType = Undefined, + translated_ip: str | UndefinedType = Undefined, + translated_port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StaticItem. + + + Subclass of AvdModel. + + Args: + access_list: 'access_list' and 'group' are mutual exclusive. + comment: comment + direction: + Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware + platform. + EOS might remove this keyword in the configuration. So, check the configuration on + targeted HW/SW. + group: 'access_list' and 'group' are mutual exclusive. + original_ip: IPv4 address. The combination of `original_ip` and `original_port` must be unique. + original_port: TCP/UDP port. The combination of `original_ip` and `original_port` must be unique. + priority: priority + protocol: protocol + translated_ip: IPv4 address. + translated_port: requires 'original_port'. + _custom_data: _custom_data + + """ + + class Static(AvdList[StaticItem]): + """Subclass of AvdList with `StaticItem` items.""" + + Static._item_type = StaticItem + + _fields: ClassVar[dict] = {"dynamic": {"type": Dynamic}, "static": {"type": Static}, "_custom_data": {"type": dict}} + dynamic: Dynamic + """Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`).""" + static: Static + """Subclass of AvdList with `StaticItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dynamic: Dynamic | UndefinedType = Undefined, + static: Static | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Source. + + + Subclass of AvdModel. + + Args: + dynamic: Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`). + static: Subclass of AvdList with `StaticItem` items. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "vrf": {"type": str}, + "destination": {"type": Destination}, + "source": {"type": Source}, + "_custom_data": {"type": dict}, + } + name: str + vrf: str | None + """Specify VRF for NAT profile.""" + destination: Destination + """Subclass of AvdModel.""" + source: Source + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + destination: Destination | UndefinedType = Undefined, + source: Source | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ProfilesItem. + + + Subclass of AvdModel. + + Args: + name: name + vrf: Specify VRF for NAT profile. + destination: Subclass of AvdModel. + source: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Profiles(AvdIndexedList[str, ProfilesItem]): + """Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Profiles._item_type = ProfilesItem + + class PoolsItem(AvdModel): + """Subclass of AvdModel.""" + + class RangesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "first_ip": {"type": str}, + "last_ip": {"type": str}, + "first_port": {"type": int}, + "last_port": {"type": int}, + "_custom_data": {"type": dict}, + } + first_ip: str | None + """ + IPv4 address. + Required when `type` is `ip-port` and ignored otherwise. + """ + last_ip: str | None + """ + IPv4 address. + Required when `type` is `ip-port` and ignored otherwise. + `first_ip` and `last_ip` ip + addresses should lie in same subnet. + """ + first_port: int | None + last_port: int | None + """ + Required when `first_port` is set. + `last_port` must be greater than or equal to `first_port`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + first_ip: str | None | UndefinedType = Undefined, + last_ip: str | None | UndefinedType = Undefined, + first_port: int | None | UndefinedType = Undefined, + last_port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RangesItem. + + + Subclass of AvdModel. + + Args: + first_ip: + IPv4 address. + Required when `type` is `ip-port` and ignored otherwise. + last_ip: + IPv4 address. + Required when `type` is `ip-port` and ignored otherwise. + `first_ip` and `last_ip` ip + addresses should lie in same subnet. + first_port: first_port + last_port: + Required when `first_port` is set. + `last_port` must be greater than or equal to `first_port`. + _custom_data: _custom_data + + """ + + class Ranges(AvdList[RangesItem]): + """Subclass of AvdList with `RangesItem` items.""" + + Ranges._item_type = RangesItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "type": {"type": str, "default": "ip-port"}, + "prefix_length": {"type": int}, + "ranges": {"type": Ranges}, + "utilization_log_threshold": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str + type: Literal["ip-port", "port-only"] + """Default value: `"ip-port"`""" + prefix_length: int | None + """It is only used and required when `type` is `ip-port`.""" + ranges: Ranges + """Subclass of AvdList with `RangesItem` items.""" + utilization_log_threshold: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + type: Literal["ip-port", "port-only"] | UndefinedType = Undefined, + prefix_length: int | None | UndefinedType = Undefined, + ranges: Ranges | UndefinedType = Undefined, + utilization_log_threshold: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PoolsItem. + + + Subclass of AvdModel. + + Args: + name: name + type: type + prefix_length: It is only used and required when `type` is `ip-port`. + ranges: Subclass of AvdList with `RangesItem` items. + utilization_log_threshold: utilization_log_threshold + _custom_data: _custom_data + + """ + + class Pools(AvdIndexedList[str, PoolsItem]): + """Subclass of AvdIndexedList with `PoolsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Pools._item_type = PoolsItem + + class Synchronization(AvdModel): + """Subclass of AvdModel.""" + + class PortRange(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "first_port": {"type": int}, + "last_port": {"type": int}, + "split_disabled": {"type": bool}, + "_custom_data": {"type": dict}, + } + first_port: int | None + last_port: int | None + """>= first_port.""" + split_disabled: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + first_port: int | None | UndefinedType = Undefined, + last_port: int | None | UndefinedType = Undefined, + split_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PortRange. + + + Subclass of AvdModel. + + Args: + first_port: first_port + last_port: >= first_port. + split_disabled: split_disabled + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "description": {"type": str}, + "expiry_interval": {"type": int}, + "local_interface": {"type": str}, + "peer_address": {"type": str}, + "port_range": {"type": PortRange}, + "shutdown": {"type": bool}, + "_custom_data": {"type": dict}, + } + description: str | None + expiry_interval: int | None + """In seconds.""" + local_interface: str | None + """EOS interface name.""" + peer_address: str | None + """IPv4 address.""" + port_range: PortRange + """Subclass of AvdModel.""" + shutdown: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + description: str | None | UndefinedType = Undefined, + expiry_interval: int | None | UndefinedType = Undefined, + local_interface: str | None | UndefinedType = Undefined, + peer_address: str | None | UndefinedType = Undefined, + port_range: PortRange | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Synchronization. + + + Subclass of AvdModel. + + Args: + description: description + expiry_interval: In seconds. + local_interface: EOS interface name. + peer_address: IPv4 address. + port_range: Subclass of AvdModel. + shutdown: shutdown + _custom_data: _custom_data + + """ + + class Translation(AvdModel): + """Subclass of AvdModel.""" + + class AddressSelection(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"any": {"type": bool}, "hash_field_source_ip": {"type": bool}, "_custom_data": {"type": dict}} + any: bool | None + hash_field_source_ip: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + any: bool | None | UndefinedType = Undefined, + hash_field_source_ip: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressSelection. + + + Subclass of AvdModel. + + Args: + any: any + hash_field_source_ip: hash_field_source_ip + _custom_data: _custom_data + + """ + + class LowMark(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"percentage": {"type": int}, "host_percentage": {"type": int}, "_custom_data": {"type": dict}} + percentage: int | None + """Used to render 'ip nat translation low-mark '.""" + host_percentage: int | None + """Used to render 'ip nat translation low-mark host'.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + percentage: int | None | UndefinedType = Undefined, + host_percentage: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LowMark. + + + Subclass of AvdModel. + + Args: + percentage: Used to render 'ip nat translation low-mark '. + host_percentage: Used to render 'ip nat translation low-mark host'. + _custom_data: _custom_data + + """ + + class MaxEntries(AvdModel): + """Subclass of AvdModel.""" + + class IpLimitsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ip": {"type": str}, "limit": {"type": int}, "_custom_data": {"type": dict}} + ip: str + """IPv4 address.""" + limit: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip: str | UndefinedType = Undefined, + limit: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpLimitsItem. + + + Subclass of AvdModel. + + Args: + ip: IPv4 address. + limit: limit + _custom_data: _custom_data + + """ + + class IpLimits(AvdIndexedList[str, IpLimitsItem]): + """Subclass of AvdIndexedList with `IpLimitsItem` items. Primary key is `ip` (`str`).""" + + _primary_key: ClassVar[str] = "ip" + + IpLimits._item_type = IpLimitsItem + + _fields: ClassVar[dict] = {"limit": {"type": int}, "host_limit": {"type": int}, "ip_limits": {"type": IpLimits}, "_custom_data": {"type": dict}} + limit: int | None + host_limit: int | None + ip_limits: IpLimits + """Subclass of AvdIndexedList with `IpLimitsItem` items. Primary key is `ip` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + limit: int | None | UndefinedType = Undefined, + host_limit: int | None | UndefinedType = Undefined, + ip_limits: IpLimits | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MaxEntries. + + + Subclass of AvdModel. + + Args: + limit: limit + host_limit: host_limit + ip_limits: Subclass of AvdIndexedList with `IpLimitsItem` items. Primary key is `ip` (`str`). + _custom_data: _custom_data + + """ + + class TimeoutsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"protocol": {"type": str}, "timeout": {"type": int}, "_custom_data": {"type": dict}} + protocol: Literal["tcp", "udp"] + timeout: int + """In seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + protocol: Literal["tcp", "udp"] | UndefinedType = Undefined, + timeout: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TimeoutsItem. + + + Subclass of AvdModel. + + Args: + protocol: protocol + timeout: In seconds. + _custom_data: _custom_data + + """ + + class Timeouts(AvdIndexedList[str, TimeoutsItem]): + """Subclass of AvdIndexedList with `TimeoutsItem` items. Primary key is `protocol` (`str`).""" + + _primary_key: ClassVar[str] = "protocol" + + Timeouts._item_type = TimeoutsItem + + _fields: ClassVar[dict] = { + "address_selection": {"type": AddressSelection}, + "counters": {"type": bool}, + "low_mark": {"type": LowMark}, + "max_entries": {"type": MaxEntries}, + "timeouts": {"type": Timeouts}, + "_custom_data": {"type": dict}, + } + address_selection: AddressSelection + """Subclass of AvdModel.""" + counters: bool | None + low_mark: LowMark + """Subclass of AvdModel.""" + max_entries: MaxEntries + """Subclass of AvdModel.""" + timeouts: Timeouts + """Subclass of AvdIndexedList with `TimeoutsItem` items. Primary key is `protocol` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + address_selection: AddressSelection | UndefinedType = Undefined, + counters: bool | None | UndefinedType = Undefined, + low_mark: LowMark | UndefinedType = Undefined, + max_entries: MaxEntries | UndefinedType = Undefined, + timeouts: Timeouts | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Translation. + + + Subclass of AvdModel. + + Args: + address_selection: Subclass of AvdModel. + counters: counters + low_mark: Subclass of AvdModel. + max_entries: Subclass of AvdModel. + timeouts: Subclass of AvdIndexedList with `TimeoutsItem` items. Primary key is `protocol` (`str`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "kernel_buffer_size": {"type": int}, + "profiles": {"type": Profiles}, + "pools": {"type": Pools}, + "synchronization": {"type": Synchronization}, + "translation": {"type": Translation}, + "_custom_data": {"type": dict}, + } + kernel_buffer_size: int | None + """Buffer size in MB.""" + profiles: Profiles + """Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `name` (`str`).""" + pools: Pools + """Subclass of AvdIndexedList with `PoolsItem` items. Primary key is `name` (`str`).""" + synchronization: Synchronization + """Subclass of AvdModel.""" + translation: Translation + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + kernel_buffer_size: int | None | UndefinedType = Undefined, + profiles: Profiles | UndefinedType = Undefined, + pools: Pools | UndefinedType = Undefined, + synchronization: Synchronization | UndefinedType = Undefined, + translation: Translation | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpNat. + + + Subclass of AvdModel. + + Args: + kernel_buffer_size: Buffer size in MB. + profiles: Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `name` (`str`). + pools: Subclass of AvdIndexedList with `PoolsItem` items. Primary key is `name` (`str`). + synchronization: Subclass of AvdModel. + translation: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class IpRadiusSourceInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + """Interface Name.""" + vrf: str | None + """VRF Name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpRadiusSourceInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: Interface Name. + vrf: VRF Name. + _custom_data: _custom_data + + """ + + class IpRadiusSourceInterfaces(AvdList[IpRadiusSourceInterfacesItem]): + """Subclass of AvdList with `IpRadiusSourceInterfacesItem` items.""" + + IpRadiusSourceInterfaces._item_type = IpRadiusSourceInterfacesItem + + class IpSecurity(AvdModel): + """Subclass of AvdModel.""" + + class IkePoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "local_id": {"type": str}, + "local_id_fqdn": {"type": str}, + "ike_lifetime": {"type": int}, + "encryption": {"type": str}, + "dh_group": {"type": int}, + "integrity": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Policy name.""" + local_id: str | None + """ + Local IKE identification. + Can be an IPv4 or an IPv6 address. + If both `local_id` and `local_id_fqdn` + are set, `local_id_fqdn` takes precedence. + """ + local_id_fqdn: str | None + """ + Local FQDN or UFQDN IKE identification. + If both `local_id` and `local_id_fqdn` are set, + `local_id_fqdn` takes precedence. + """ + ike_lifetime: int | None + """IKE lifetime in hours.""" + encryption: Literal["3des", "aes128", "aes256"] | None + """IKE encryption algorithm.""" + dh_group: Literal[1, 2, 5, 14, 15, 16, 17, 20, 21, 24] | None + """Diffie-Hellman group for the key exchange.""" + integrity: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None + """Integrity algorithm.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + local_id: str | None | UndefinedType = Undefined, + local_id_fqdn: str | None | UndefinedType = Undefined, + ike_lifetime: int | None | UndefinedType = Undefined, + encryption: Literal["3des", "aes128", "aes256"] | None | UndefinedType = Undefined, + dh_group: Literal[1, 2, 5, 14, 15, 16, 17, 20, 21, 24] | None | UndefinedType = Undefined, + integrity: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IkePoliciesItem. + + + Subclass of AvdModel. + + Args: + name: Policy name. + local_id: + Local IKE identification. + Can be an IPv4 or an IPv6 address. + If both `local_id` and `local_id_fqdn` + are set, `local_id_fqdn` takes precedence. + local_id_fqdn: + Local FQDN or UFQDN IKE identification. + If both `local_id` and `local_id_fqdn` are set, + `local_id_fqdn` takes precedence. + ike_lifetime: IKE lifetime in hours. + encryption: IKE encryption algorithm. + dh_group: Diffie-Hellman group for the key exchange. + integrity: Integrity algorithm. + _custom_data: _custom_data + + """ + + class IkePolicies(AvdIndexedList[str, IkePoliciesItem]): + """Subclass of AvdIndexedList with `IkePoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + IkePolicies._item_type = IkePoliciesItem + + class SaPoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + class SaLifetime(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"value": {"type": int}, "unit": {"type": str, "default": "hours"}, "_custom_data": {"type": dict}} + value: int | None + """ + Lifetime value for this SA. + Valid range depends on the unit. + <1-24> Lifetime in hours ( + default ) + <1-4000000> Packet limit in thousands + <1-6000> Byte limit in GB ( 1024 MB ) + <1-6144000> Byte limit in MB ( 1024 KB ) + """ + unit: Literal["gigabytes", "hours", "megabytes", "thousand-packets"] + """Default value: `"hours"`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + value: int | None | UndefinedType = Undefined, + unit: Literal["gigabytes", "hours", "megabytes", "thousand-packets"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SaLifetime. + + + Subclass of AvdModel. + + Args: + value: + Lifetime value for this SA. + Valid range depends on the unit. + <1-24> Lifetime in hours ( + default ) + <1-4000000> Packet limit in thousands + <1-6000> Byte limit in GB ( 1024 MB ) + <1-6144000> Byte limit in MB ( 1024 KB ) + unit: unit + _custom_data: _custom_data + + """ + + class Esp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"integrity": {"type": str}, "encryption": {"type": str}, "_custom_data": {"type": dict}} + integrity: Literal["disabled", "sha1", "sha256", "sha384", "sha512", "md5"] | None + encryption: Literal["disabled", "aes128", "aes128gcm128", "aes128gcm64", "aes256", "aes256gcm128", "3des"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + integrity: Literal["disabled", "sha1", "sha256", "sha384", "sha512", "md5"] | None | UndefinedType = Undefined, + encryption: Literal["disabled", "aes128", "aes128gcm128", "aes128gcm64", "aes256", "aes256gcm128", "3des"] + | None + | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Esp. + + + Subclass of AvdModel. + + Args: + integrity: integrity + encryption: encryption + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "sa_lifetime": {"type": SaLifetime}, + "esp": {"type": Esp}, + "pfs_dh_group": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str + """Name of the SA policy.""" + sa_lifetime: SaLifetime + """Subclass of AvdModel.""" + esp: Esp + """Subclass of AvdModel.""" + pfs_dh_group: Literal[1, 2, 5, 14, 15, 16, 17, 20, 21, 24] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + sa_lifetime: SaLifetime | UndefinedType = Undefined, + esp: Esp | UndefinedType = Undefined, + pfs_dh_group: Literal[1, 2, 5, 14, 15, 16, 17, 20, 21, 24] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SaPoliciesItem. + + + Subclass of AvdModel. + + Args: + name: Name of the SA policy. + sa_lifetime: Subclass of AvdModel. + esp: Subclass of AvdModel. + pfs_dh_group: pfs_dh_group + _custom_data: _custom_data + + """ + + class SaPolicies(AvdIndexedList[str, SaPoliciesItem]): + """Subclass of AvdIndexedList with `SaPoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + SaPolicies._item_type = SaPoliciesItem + + class ProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class Dpd(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interval": {"type": int}, "time": {"type": int}, "action": {"type": str}, "_custom_data": {"type": dict}} + interval: int + """Interval (in seconds) between keep-alive messages.""" + time: int + """Time (in seconds) after which the action is applied.""" + action: Literal["clear", "hold", "restart"] + """ + Action to apply. + + * 'clear': Delete all connections + * 'hold': Re-negotiate connection on demand + * + 'restart': Restart connection immediately + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | UndefinedType = Undefined, + time: int | UndefinedType = Undefined, + action: Literal["clear", "hold", "restart"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dpd. + + + Subclass of AvdModel. + + Args: + interval: Interval (in seconds) between keep-alive messages. + time: Time (in seconds) after which the action is applied. + action: + Action to apply. + + * 'clear': Delete all connections + * 'hold': Re-negotiate connection on demand + * + 'restart': Restart connection immediately + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "ike_policy": {"type": str}, + "sa_policy": {"type": str}, + "connection": {"type": str}, + "shared_key": {"type": str}, + "dpd": {"type": Dpd}, + "mode": {"type": str}, + "flow_parallelization_encapsulation_udp": {"type": bool}, + "_custom_data": {"type": dict}, + } + name: str + """Name of the IPsec profile.""" + ike_policy: str | None + """Name of the IKE policy to use in this profile.""" + sa_policy: str | None + """Name of the Security Association to use in this profile.""" + connection: Literal["add", "start", "route"] | None + """IPsec connection (Initiator/Responder/Dynamic).""" + shared_key: str | None + """Encrypted password - only type 7 supported.""" + dpd: Dpd + """ + Dead Peer Detection. + + Subclass of AvdModel. + """ + mode: Literal["transport", "tunnel"] | None + """Ipsec mode type.""" + flow_parallelization_encapsulation_udp: bool | None + """ + Enable flow parallelization. + When enabled, multiple cores are used to parallelize the IPsec + encryption and decryption processing. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + ike_policy: str | None | UndefinedType = Undefined, + sa_policy: str | None | UndefinedType = Undefined, + connection: Literal["add", "start", "route"] | None | UndefinedType = Undefined, + shared_key: str | None | UndefinedType = Undefined, + dpd: Dpd | UndefinedType = Undefined, + mode: Literal["transport", "tunnel"] | None | UndefinedType = Undefined, + flow_parallelization_encapsulation_udp: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ProfilesItem. + + + Subclass of AvdModel. + + Args: + name: Name of the IPsec profile. + ike_policy: Name of the IKE policy to use in this profile. + sa_policy: Name of the Security Association to use in this profile. + connection: IPsec connection (Initiator/Responder/Dynamic). + shared_key: Encrypted password - only type 7 supported. + dpd: + Dead Peer Detection. + + Subclass of AvdModel. + mode: Ipsec mode type. + flow_parallelization_encapsulation_udp: + Enable flow parallelization. + When enabled, multiple cores are used to parallelize the IPsec + encryption and decryption processing. + _custom_data: _custom_data + + """ + + class Profiles(AvdIndexedList[str, ProfilesItem]): + """Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Profiles._item_type = ProfilesItem + + class KeyController(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "_custom_data": {"type": dict}} + profile: str | None + """IPsec profile name to use.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, profile: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + KeyController. + + + Subclass of AvdModel. + + Args: + profile: IPsec profile name to use. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ike_policies": {"type": IkePolicies}, + "sa_policies": {"type": SaPolicies}, + "profiles": {"type": Profiles}, + "key_controller": {"type": KeyController}, + "hardware_encryption_disabled": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + ike_policies: IkePolicies + """ + Internet Security Association and Key Mgmt Protocol. + + Subclass of AvdIndexedList with + `IkePoliciesItem` items. Primary key is `name` (`str`). + """ + sa_policies: SaPolicies + """ + Security Association policies. + + Subclass of AvdIndexedList with `SaPoliciesItem` items. Primary key + is `name` (`str`). + """ + profiles: Profiles + """ + IPSec profiles. + + Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `name` + (`str`). + """ + key_controller: KeyController + """Subclass of AvdModel.""" + hardware_encryption_disabled: bool + """ + Disable hardware encryption. + An SFE restart is needed for this change to take effect. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ike_policies: IkePolicies | UndefinedType = Undefined, + sa_policies: SaPolicies | UndefinedType = Undefined, + profiles: Profiles | UndefinedType = Undefined, + key_controller: KeyController | UndefinedType = Undefined, + hardware_encryption_disabled: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpSecurity. + + + Subclass of AvdModel. + + Args: + ike_policies: + Internet Security Association and Key Mgmt Protocol. + + Subclass of AvdIndexedList with + `IkePoliciesItem` items. Primary key is `name` (`str`). + sa_policies: + Security Association policies. + + Subclass of AvdIndexedList with `SaPoliciesItem` items. Primary key + is `name` (`str`). + profiles: + IPSec profiles. + + Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `name` + (`str`). + key_controller: Subclass of AvdModel. + hardware_encryption_disabled: + Disable hardware encryption. + An SFE restart is needed for this change to take effect. + _custom_data: _custom_data + + """ + + class IpSshClientSourceInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "vrf": {"type": str, "default": "default"}, "_custom_data": {"type": dict}} + name: str | None + """Interface Name.""" + vrf: str + """Default value: `"default"`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + vrf: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpSshClientSourceInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: Interface Name. + vrf: vrf + _custom_data: _custom_data + + """ + + class IpSshClientSourceInterfaces(AvdList[IpSshClientSourceInterfacesItem]): + """Subclass of AvdList with `IpSshClientSourceInterfacesItem` items.""" + + IpSshClientSourceInterfaces._item_type = IpSshClientSourceInterfacesItem + + class IpTacacsSourceInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + """Interface name.""" + vrf: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpTacacsSourceInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: Interface name. + vrf: vrf + _custom_data: _custom_data + + """ + + class IpTacacsSourceInterfaces(AvdList[IpTacacsSourceInterfacesItem]): + """Subclass of AvdList with `IpTacacsSourceInterfacesItem` items.""" + + IpTacacsSourceInterfaces._item_type = IpTacacsSourceInterfacesItem + + class IpTelnetClientSourceInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Interface Name.""" + vrf: str | None + """VRF Name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpTelnetClientSourceInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: Interface Name. + vrf: VRF Name. + _custom_data: _custom_data + + """ + + class IpTelnetClientSourceInterfaces(AvdList[IpTelnetClientSourceInterfacesItem]): + """Subclass of AvdList with `IpTelnetClientSourceInterfacesItem` items.""" + + IpTelnetClientSourceInterfaces._item_type = IpTelnetClientSourceInterfacesItem + + class IpTftpClientSourceInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Interface Name.""" + vrf: str | None + """VRF Name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpTftpClientSourceInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: Interface Name. + vrf: VRF Name. + _custom_data: _custom_data + + """ + + class IpTftpClientSourceInterfaces(AvdList[IpTftpClientSourceInterfacesItem]): + """Subclass of AvdList with `IpTftpClientSourceInterfacesItem` items.""" + + IpTftpClientSourceInterfaces._item_type = IpTftpClientSourceInterfacesItem + + class Ipv6AccessListsItem(AvdModel): + """Subclass of AvdModel.""" + + class SequenceNumbersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"sequence": {"type": int}, "action": {"type": str}, "_custom_data": {"type": dict}} + sequence: int + """Sequence ID.""" + action: str + """ + Action as string. + Example: "deny ipv6 any any" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sequence: int | UndefinedType = Undefined, + action: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceNumbersItem. + + + Subclass of AvdModel. + + Args: + sequence: Sequence ID. + action: + Action as string. + Example: "deny ipv6 any any" + _custom_data: _custom_data + + """ + + class SequenceNumbers(AvdIndexedList[int, SequenceNumbersItem]): + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + + _primary_key: ClassVar[str] = "sequence" + + SequenceNumbers._item_type = SequenceNumbersItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "counters_per_entry": {"type": bool}, + "sequence_numbers": {"type": SequenceNumbers}, + "_custom_data": {"type": dict}, + } + name: str + """IPv6 Access-list Name.""" + counters_per_entry: bool | None + sequence_numbers: SequenceNumbers + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + counters_per_entry: bool | None | UndefinedType = Undefined, + sequence_numbers: SequenceNumbers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6AccessListsItem. + + + Subclass of AvdModel. + + Args: + name: IPv6 Access-list Name. + counters_per_entry: counters_per_entry + sequence_numbers: Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`). + _custom_data: _custom_data + + """ + + class Ipv6AccessLists(AvdIndexedList[str, Ipv6AccessListsItem]): + """Subclass of AvdIndexedList with `Ipv6AccessListsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Ipv6AccessLists._item_type = Ipv6AccessListsItem + + class Ipv6DhcpRelay(AvdModel): + """Subclass of AvdModel.""" + + class Option(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"link_layer_address": {"type": bool}, "remote_id_format": {"type": str}, "_custom_data": {"type": dict}} + link_layer_address: bool | None + """Add Option 79 (Link Layer Address Option).""" + remote_id_format: Literal["%m:%i", "%m:%p"] | None + """ + Add RemoteID option 37 in format MAC address and interface ID (`%m:%i`) or MAC address and interface + name (`%m:%p`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + link_layer_address: bool | None | UndefinedType = Undefined, + remote_id_format: Literal["%m:%i", "%m:%p"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Option. + + + Subclass of AvdModel. + + Args: + link_layer_address: Add Option 79 (Link Layer Address Option). + remote_id_format: + Add RemoteID option 37 in format MAC address and interface ID (`%m:%i`) or MAC address and interface + name (`%m:%p`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"always_on": {"type": bool}, "all_subnets": {"type": bool}, "option": {"type": Option}, "_custom_data": {"type": dict}} + always_on: bool | None + """DhcpRelay Agent will be in always-on mode, off by default.""" + all_subnets: bool | None + """Allow forwarding requests with additional IPv6 addresses in the gateway address "giaddr" field.""" + option: Option + """ + Insert DHCP Option. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + always_on: bool | None | UndefinedType = Undefined, + all_subnets: bool | None | UndefinedType = Undefined, + option: Option | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6DhcpRelay. + + + Subclass of AvdModel. + + Args: + always_on: DhcpRelay Agent will be in always-on mode, off by default. + all_subnets: Allow forwarding requests with additional IPv6 addresses in the gateway address "giaddr" field. + option: + Insert DHCP Option. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Ipv6Hardware(AvdModel): + """Subclass of AvdModel.""" + + class Fib(AvdModel): + """Subclass of AvdModel.""" + + class Optimize(AvdModel): + """Subclass of AvdModel.""" + + class Prefixes(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "_custom_data": {"type": dict}} + profile: str | None + """Pre-defined profile 'internet' or user-defined profile name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, profile: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Prefixes. + + + Subclass of AvdModel. + + Args: + profile: Pre-defined profile 'internet' or user-defined profile name. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"prefixes": {"type": Prefixes}, "_custom_data": {"type": dict}} + prefixes: Prefixes + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, prefixes: Prefixes | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Optimize. + + + Subclass of AvdModel. + + Args: + prefixes: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"optimize": {"type": Optimize}, "_custom_data": {"type": dict}} + optimize: Optimize + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, optimize: Optimize | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Fib. + + + Subclass of AvdModel. + + Args: + optimize: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"fib": {"type": Fib}, "_custom_data": {"type": dict}} + fib: Fib + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, fib: Fib | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Ipv6Hardware. + + + Subclass of AvdModel. + + Args: + fib: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Ipv6Neighbor(AvdModel): + """Subclass of AvdModel.""" + + class StaticEntriesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "ipv6_address": {"type": str}, + "vrf": {"type": str}, + "interface": {"type": str}, + "mac_address": {"type": str}, + "_custom_data": {"type": dict}, + } + ipv6_address: str + """IPv6 address of neighbor.""" + vrf: str | None + interface: str + """Interface name.""" + mac_address: str + """MAC address of neighbor like 'aa:af:12:34:bc:bf'""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv6_address: str | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + interface: str | UndefinedType = Undefined, + mac_address: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StaticEntriesItem. + + + Subclass of AvdModel. + + Args: + ipv6_address: IPv6 address of neighbor. + vrf: vrf + interface: Interface name. + mac_address: MAC address of neighbor like 'aa:af:12:34:bc:bf' + _custom_data: _custom_data + + """ + + class StaticEntries(AvdList[StaticEntriesItem]): + """Subclass of AvdList with `StaticEntriesItem` items.""" + + StaticEntries._item_type = StaticEntriesItem + + class Persistent(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "refresh_delay": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool + """Restore the IPv6 neighbor cache after reboot.""" + refresh_delay: int | None + """ + Time to wait in seconds before refreshing the IPv6 neighbor cache after reboot (EOS default 600). + It + will require setting the `enabled` key to true. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + refresh_delay: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Persistent. + + + Subclass of AvdModel. + + Args: + enabled: Restore the IPv6 neighbor cache after reboot. + refresh_delay: + Time to wait in seconds before refreshing the IPv6 neighbor cache after reboot (EOS default 600). + It + will require setting the `enabled` key to true. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"static_entries": {"type": StaticEntries}, "persistent": {"type": Persistent}, "_custom_data": {"type": dict}} + static_entries: StaticEntries + """ + Static IPv6 neighbor entries. + + Subclass of AvdList with `StaticEntriesItem` items. + """ + persistent: Persistent + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + static_entries: StaticEntries | UndefinedType = Undefined, + persistent: Persistent | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6Neighbor. + + + Subclass of AvdModel. + + Args: + static_entries: + Static IPv6 neighbor entries. + + Subclass of AvdList with `StaticEntriesItem` items. + persistent: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Ipv6PrefixListsItem(AvdModel): + """Subclass of AvdModel.""" + + class SequenceNumbersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"sequence": {"type": int}, "action": {"type": str}, "_custom_data": {"type": dict}} + sequence: int + """Sequence ID.""" + action: str + """ + Action as string. + Example: "permit 1b11:3a00:22b0:0082::/64 eq 128" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sequence: int | UndefinedType = Undefined, + action: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceNumbersItem. + + + Subclass of AvdModel. + + Args: + sequence: Sequence ID. + action: + Action as string. + Example: "permit 1b11:3a00:22b0:0082::/64 eq 128" + _custom_data: _custom_data + + """ + + class SequenceNumbers(AvdIndexedList[int, SequenceNumbersItem]): + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + + _primary_key: ClassVar[str] = "sequence" + + SequenceNumbers._item_type = SequenceNumbersItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "sequence_numbers": {"type": SequenceNumbers}, "_custom_data": {"type": dict}} + name: str + """Prefix-list Name.""" + sequence_numbers: SequenceNumbers + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + sequence_numbers: SequenceNumbers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6PrefixListsItem. + + + Subclass of AvdModel. + + Args: + name: Prefix-list Name. + sequence_numbers: Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`). + _custom_data: _custom_data + + """ + + class Ipv6PrefixLists(AvdIndexedList[str, Ipv6PrefixListsItem]): + """Subclass of AvdIndexedList with `Ipv6PrefixListsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Ipv6PrefixLists._item_type = Ipv6PrefixListsItem + + class Ipv6StandardAccessListsItem(AvdModel): + """Subclass of AvdModel.""" + + class SequenceNumbersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"sequence": {"type": int}, "action": {"type": str}, "_custom_data": {"type": dict}} + sequence: int + """Sequence ID.""" + action: str + """ + Action as string. + Example: "deny ipv6 any any" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sequence: int | UndefinedType = Undefined, + action: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceNumbersItem. + + + Subclass of AvdModel. + + Args: + sequence: Sequence ID. + action: + Action as string. + Example: "deny ipv6 any any" + _custom_data: _custom_data + + """ + + class SequenceNumbers(AvdIndexedList[int, SequenceNumbersItem]): + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + + _primary_key: ClassVar[str] = "sequence" + + SequenceNumbers._item_type = SequenceNumbersItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "counters_per_entry": {"type": bool}, + "sequence_numbers": {"type": SequenceNumbers}, + "_custom_data": {"type": dict}, + } + name: str + """Access-list Name.""" + counters_per_entry: bool | None + sequence_numbers: SequenceNumbers + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + counters_per_entry: bool | None | UndefinedType = Undefined, + sequence_numbers: SequenceNumbers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6StandardAccessListsItem. + + + Subclass of AvdModel. + + Args: + name: Access-list Name. + counters_per_entry: counters_per_entry + sequence_numbers: Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`). + _custom_data: _custom_data + + """ + + class Ipv6StandardAccessLists(AvdIndexedList[str, Ipv6StandardAccessListsItem]): + """Subclass of AvdIndexedList with `Ipv6StandardAccessListsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Ipv6StandardAccessLists._item_type = Ipv6StandardAccessListsItem + + class Ipv6StaticRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "vrf": {"type": str}, + "destination_address_prefix": {"type": str}, + "interface": {"type": str}, + "gateway": {"type": str}, + "track_bfd": {"type": bool}, + "distance": {"type": int}, + "tag": {"type": int}, + "name": {"type": str}, + "metric": {"type": int}, + "_custom_data": {"type": dict}, + } + vrf: str | None + destination_address_prefix: str | None + """IPv6 Network/Mask.""" + interface: str | None + gateway: str | None + """IPv6 Address.""" + track_bfd: bool | None + """Track next-hop using BFD.""" + distance: int | None + tag: int | None + name: str | None + """Description.""" + metric: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + vrf: str | None | UndefinedType = Undefined, + destination_address_prefix: str | None | UndefinedType = Undefined, + interface: str | None | UndefinedType = Undefined, + gateway: str | None | UndefinedType = Undefined, + track_bfd: bool | None | UndefinedType = Undefined, + distance: int | None | UndefinedType = Undefined, + tag: int | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + metric: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6StaticRoutesItem. + + + Subclass of AvdModel. + + Args: + vrf: vrf + destination_address_prefix: IPv6 Network/Mask. + interface: interface + gateway: IPv6 Address. + track_bfd: Track next-hop using BFD. + distance: distance + tag: tag + name: Description. + metric: metric + _custom_data: _custom_data + + """ + + class Ipv6StaticRoutes(AvdList[Ipv6StaticRoutesItem]): + """Subclass of AvdList with `Ipv6StaticRoutesItem` items.""" + + Ipv6StaticRoutes._item_type = Ipv6StaticRoutesItem + + class L2Protocol(AvdModel): + """Subclass of AvdModel.""" + + class ForwardingProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class ProtocolsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "forward": {"type": bool}, + "tagged_forward": {"type": bool}, + "untagged_forward": {"type": bool}, + "_custom_data": {"type": dict}, + } + name: Literal["bfd per-link rfc-7130", "e-lmi", "isis", "lacp", "lldp", "macsec", "pause", "stp"] + forward: bool | None + tagged_forward: bool | None + untagged_forward: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: Literal["bfd per-link rfc-7130", "e-lmi", "isis", "lacp", "lldp", "macsec", "pause", "stp"] | UndefinedType = Undefined, + forward: bool | None | UndefinedType = Undefined, + tagged_forward: bool | None | UndefinedType = Undefined, + untagged_forward: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ProtocolsItem. + + + Subclass of AvdModel. + + Args: + name: name + forward: forward + tagged_forward: tagged_forward + untagged_forward: untagged_forward + _custom_data: _custom_data + + """ + + class Protocols(AvdIndexedList[str, ProtocolsItem]): + """Subclass of AvdIndexedList with `ProtocolsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Protocols._item_type = ProtocolsItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "protocols": {"type": Protocols}, "_custom_data": {"type": dict}} + name: str + protocols: Protocols + """Subclass of AvdIndexedList with `ProtocolsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + protocols: Protocols | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ForwardingProfilesItem. + + + Subclass of AvdModel. + + Args: + name: name + protocols: Subclass of AvdIndexedList with `ProtocolsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class ForwardingProfiles(AvdIndexedList[str, ForwardingProfilesItem]): + """Subclass of AvdIndexedList with `ForwardingProfilesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + ForwardingProfiles._item_type = ForwardingProfilesItem + + _fields: ClassVar[dict] = {"forwarding_profiles": {"type": ForwardingProfiles}, "_custom_data": {"type": dict}} + forwarding_profiles: ForwardingProfiles + """Subclass of AvdIndexedList with `ForwardingProfilesItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, forwarding_profiles: ForwardingProfiles | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + L2Protocol. + + + Subclass of AvdModel. + + Args: + forwarding_profiles: Subclass of AvdIndexedList with `ForwardingProfilesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class Lacp(AvdModel): + """Subclass of AvdModel.""" + + class PortId(AvdModel): + """Subclass of AvdModel.""" + + class Range(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"begin": {"type": int}, "end": {"type": int}, "_custom_data": {"type": dict}} + begin: int | None + """Minimum LACP port-ID range.""" + end: int | None + """Maximum LACP port-ID range.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + begin: int | None | UndefinedType = Undefined, + end: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Range. + + + Subclass of AvdModel. + + Args: + begin: Minimum LACP port-ID range. + end: Maximum LACP port-ID range. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"range": {"type": Range}, "_custom_data": {"type": dict}} + range: Range + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, range: Range | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + PortId. + + + Subclass of AvdModel. + + Args: + range: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class RateLimit(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"default": {"type": bool}, "_custom_data": {"type": dict}} + default: bool | None + """Enable LACPDU rate limiting by default on all ports.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, default: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + RateLimit. + + + Subclass of AvdModel. + + Args: + default: Enable LACPDU rate limiting by default on all ports. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "port_id": {"type": PortId}, + "rate_limit": {"type": RateLimit}, + "system_priority": {"type": int}, + "_custom_data": {"type": dict}, + } + port_id: PortId + """ + LACP port-ID range configuration. + + Subclass of AvdModel. + """ + rate_limit: RateLimit + """ + Set LACPDU rate limit options. + + Subclass of AvdModel. + """ + system_priority: int | None + """Set local system LACP priority.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + port_id: PortId | UndefinedType = Undefined, + rate_limit: RateLimit | UndefinedType = Undefined, + system_priority: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Lacp. + + + Subclass of AvdModel. + + Args: + port_id: + LACP port-ID range configuration. + + Subclass of AvdModel. + rate_limit: + Set LACPDU rate limit options. + + Subclass of AvdModel. + system_priority: Set local system LACP priority. + _custom_data: _custom_data + + """ + + class LinkTrackingGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "links_minimum": {"type": int}, "recovery_delay": {"type": int}, "_custom_data": {"type": dict}} + name: str + links_minimum: int | None + recovery_delay: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + links_minimum: int | None | UndefinedType = Undefined, + recovery_delay: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkTrackingGroupsItem. + + + Subclass of AvdModel. + + Args: + name: name + links_minimum: links_minimum + recovery_delay: recovery_delay + _custom_data: _custom_data + + """ + + class LinkTrackingGroups(AvdIndexedList[str, LinkTrackingGroupsItem]): + """Subclass of AvdIndexedList with `LinkTrackingGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + LinkTrackingGroups._item_type = LinkTrackingGroupsItem + + class Lldp(AvdModel): + """Subclass of AvdModel.""" + + class TlvsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "transmit": {"type": bool}, "_custom_data": {"type": dict}} + name: Literal[ + "link-aggregation", + "management-address", + "max-frame-size", + "med", + "port-description", + "port-vlan", + "power-via-mdi", + "system-capabilities", + "system-description", + "system-name", + "vlan-name", + ] + transmit: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: Literal[ + "link-aggregation", + "management-address", + "max-frame-size", + "med", + "port-description", + "port-vlan", + "power-via-mdi", + "system-capabilities", + "system-description", + "system-name", + "vlan-name", + ] + | UndefinedType = Undefined, + transmit: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TlvsItem. + + + Subclass of AvdModel. + + Args: + name: name + transmit: transmit + _custom_data: _custom_data + + """ + + class Tlvs(AvdIndexedList[str, TlvsItem]): + """Subclass of AvdIndexedList with `TlvsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Tlvs._item_type = TlvsItem + + _fields: ClassVar[dict] = { + "timer": {"type": int}, + "timer_reinitialization": {"type": str}, + "holdtime": {"type": int}, + "management_address": {"type": str}, + "vrf": {"type": str}, + "receive_packet_tagged_drop": {"type": str}, + "tlvs": {"type": Tlvs}, + "run": {"type": bool}, + "_custom_data": {"type": dict}, + } + timer: int | None + timer_reinitialization: str | None + holdtime: int | None + management_address: str | None + vrf: str | None + receive_packet_tagged_drop: str | None + tlvs: Tlvs + """Subclass of AvdIndexedList with `TlvsItem` items. Primary key is `name` (`str`).""" + run: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + timer: int | None | UndefinedType = Undefined, + timer_reinitialization: str | None | UndefinedType = Undefined, + holdtime: int | None | UndefinedType = Undefined, + management_address: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + receive_packet_tagged_drop: str | None | UndefinedType = Undefined, + tlvs: Tlvs | UndefinedType = Undefined, + run: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Lldp. + + + Subclass of AvdModel. + + Args: + timer: timer + timer_reinitialization: timer_reinitialization + holdtime: holdtime + management_address: management_address + vrf: vrf + receive_packet_tagged_drop: receive_packet_tagged_drop + tlvs: Subclass of AvdIndexedList with `TlvsItem` items. Primary key is `name` (`str`). + run: run + _custom_data: _custom_data + + """ + + class LoadInterval(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"default": {"type": int}, "_custom_data": {"type": dict}} + default: int | None + """Default load interval in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, default: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + LoadInterval. + + + Subclass of AvdModel. + + Args: + default: Default load interval in seconds. + _custom_data: _custom_data + + """ + + class LocalUsersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "disabled": {"type": bool}, + "privilege": {"type": int}, + "role": {"type": str}, + "sha512_password": {"type": str}, + "no_password": {"type": bool}, + "ssh_key": {"type": str}, + "secondary_ssh_key": {"type": str}, + "shell": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Username.""" + disabled: bool | None + """ + If true, the user will be removed and all other settings are ignored. + Useful for removing the + default "admin" user. + """ + privilege: int | None + """Initial privilege level with local EXEC authorization.""" + role: str | None + """EOS RBAC Role to be assigned to the user such as "network-admin" or "network-operator".""" + sha512_password: str | None + """ + SHA512 Hash of Password. + Must be the hash of the password. By default EOS salts the password with + the username, so the simplest is to generate the hash on an EOS device using the same username. + """ + no_password: bool | None + """ + If set a password will not be configured for this user. "sha512_password" MUST not be defined for + this user. + """ + ssh_key: str | None + secondary_ssh_key: str | None + shell: Literal["/bin/bash", "/bin/sh", "/sbin/nologin"] | None + """Specify shell for the user.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + disabled: bool | None | UndefinedType = Undefined, + privilege: int | None | UndefinedType = Undefined, + role: str | None | UndefinedType = Undefined, + sha512_password: str | None | UndefinedType = Undefined, + no_password: bool | None | UndefinedType = Undefined, + ssh_key: str | None | UndefinedType = Undefined, + secondary_ssh_key: str | None | UndefinedType = Undefined, + shell: Literal["/bin/bash", "/bin/sh", "/sbin/nologin"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LocalUsersItem. + + + Subclass of AvdModel. + + Args: + name: Username. + disabled: + If true, the user will be removed and all other settings are ignored. + Useful for removing the + default "admin" user. + privilege: Initial privilege level with local EXEC authorization. + role: EOS RBAC Role to be assigned to the user such as "network-admin" or "network-operator". + sha512_password: + SHA512 Hash of Password. + Must be the hash of the password. By default EOS salts the password with + the username, so the simplest is to generate the hash on an EOS device using the same username. + no_password: + If set a password will not be configured for this user. "sha512_password" MUST not be defined for + this user. + ssh_key: ssh_key + secondary_ssh_key: secondary_ssh_key + shell: Specify shell for the user. + _custom_data: _custom_data + + """ + + class LocalUsers(AvdIndexedList[str, LocalUsersItem]): + """Subclass of AvdIndexedList with `LocalUsersItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + LocalUsers._item_type = LocalUsersItem + + class Logging(AvdModel): + """Subclass of AvdModel.""" + + class Buffered(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"size": {"type": int}, "level": {"type": str}, "_custom_data": {"type": dict}} + size: int | None + level: Literal["alerts", "critical", "debugging", "emergencies", "errors", "informational", "notifications", "warnings", "disabled"] | None + """Buffer logging severity level.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + size: int | None | UndefinedType = Undefined, + level: Literal["alerts", "critical", "debugging", "emergencies", "errors", "informational", "notifications", "warnings", "disabled"] + | None + | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Buffered. + + + Subclass of AvdModel. + + Args: + size: size + level: Buffer logging severity level. + _custom_data: _custom_data + + """ + + class Synchronous(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str, "default": "critical"}, "_custom_data": {"type": dict}} + level: Literal["alerts", "all", "critical", "debugging", "emergencies", "errors", "informational", "notifications", "warnings", "disabled"] + """ + Synchronous logging severity level. + + Default value: `"critical"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: Literal["alerts", "all", "critical", "debugging", "emergencies", "errors", "informational", "notifications", "warnings", "disabled"] + | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Synchronous. + + + Subclass of AvdModel. + + Args: + level: Synchronous logging severity level. + _custom_data: _custom_data + + """ + + class Format(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "timestamp": {"type": str}, + "hostname": {"type": str}, + "sequence_numbers": {"type": bool}, + "rfc5424": {"type": bool}, + "_custom_data": {"type": dict}, + } + timestamp: ( + Literal["high-resolution", "traditional", "traditional timezone", "traditional year", "traditional timezone year", "traditional year timezone"] + | None + ) + """Timestamp format.""" + hostname: Literal["fqdn", "ipv4"] | None + """Hostname format in syslogs. For hostname _only_, remove the line. (default EOS CLI behaviour).""" + sequence_numbers: bool | None + """Add sequence numbers to log messages.""" + rfc5424: bool | None + """Forward logs in RFC5424 format.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + timestamp: Literal[ + "high-resolution", "traditional", "traditional timezone", "traditional year", "traditional timezone year", "traditional year timezone" + ] + | None + | UndefinedType = Undefined, + hostname: Literal["fqdn", "ipv4"] | None | UndefinedType = Undefined, + sequence_numbers: bool | None | UndefinedType = Undefined, + rfc5424: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Format. + + + Subclass of AvdModel. + + Args: + timestamp: Timestamp format. + hostname: Hostname format in syslogs. For hostname _only_, remove the line. (default EOS CLI behaviour). + sequence_numbers: Add sequence numbers to log messages. + rfc5424: Forward logs in RFC5424 format. + _custom_data: _custom_data + + """ + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + class HostsItem(AvdModel): + """Subclass of AvdModel.""" + + class Ports(AvdList[int]): + """Subclass of AvdList with `int` items.""" + + Ports._item_type = int + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "protocol": {"type": str, "default": "udp"}, + "ports": {"type": Ports}, + "_custom_data": {"type": dict}, + } + name: str + """Syslog server name.""" + protocol: Literal["tcp", "udp"] + """Default value: `"udp"`""" + ports: Ports + """Subclass of AvdList with `int` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + protocol: Literal["tcp", "udp"] | UndefinedType = Undefined, + ports: Ports | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + HostsItem. + + + Subclass of AvdModel. + + Args: + name: Syslog server name. + protocol: protocol + ports: Subclass of AvdList with `int` items. + _custom_data: _custom_data + + """ + + class Hosts(AvdIndexedList[str, HostsItem]): + """Subclass of AvdIndexedList with `HostsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Hosts._item_type = HostsItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "source_interface": {"type": str}, "hosts": {"type": Hosts}, "_custom_data": {"type": dict}} + name: str + """VRF name.""" + source_interface: str | None + """Source interface name.""" + hosts: Hosts + """Subclass of AvdIndexedList with `HostsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + source_interface: str | None | UndefinedType = Undefined, + hosts: Hosts | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: VRF name. + source_interface: Source interface name. + hosts: Subclass of AvdIndexedList with `HostsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + class Policy(AvdModel): + """Subclass of AvdModel.""" + + class Match(AvdModel): + """Subclass of AvdModel.""" + + class MatchListsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "action": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Match list.""" + action: Literal["discard"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + action: Literal["discard"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchListsItem. + + + Subclass of AvdModel. + + Args: + name: Match list. + action: action + _custom_data: _custom_data + + """ + + class MatchLists(AvdIndexedList[str, MatchListsItem]): + """Subclass of AvdIndexedList with `MatchListsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + MatchLists._item_type = MatchListsItem + + _fields: ClassVar[dict] = {"match_lists": {"type": MatchLists}, "_custom_data": {"type": dict}} + match_lists: MatchLists + """Subclass of AvdIndexedList with `MatchListsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, match_lists: MatchLists | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Match. + + + Subclass of AvdModel. + + Args: + match_lists: Subclass of AvdIndexedList with `MatchListsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"match": {"type": Match}, "_custom_data": {"type": dict}} + match: Match + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, match: Match | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Policy. + + + Subclass of AvdModel. + + Args: + match: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Event(AvdModel): + """Subclass of AvdModel.""" + + class StormControl(AvdModel): + """Subclass of AvdModel.""" + + class Discards(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"field_global": {"type": bool}, "interval": {"type": int}, "_custom_data": {"type": dict}} + _field_to_key_map: ClassVar[dict] = {"field_global": "global"} + _key_to_field_map: ClassVar[dict] = {"global": "field_global"} + field_global: bool | None + interval: int | None + """Logging interval in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + field_global: bool | None | UndefinedType = Undefined, + interval: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Discards. + + + Subclass of AvdModel. + + Args: + field_global: field_global + interval: Logging interval in seconds. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"discards": {"type": Discards}, "_custom_data": {"type": dict}} + discards: Discards + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, discards: Discards | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + StormControl. + + + Subclass of AvdModel. + + Args: + discards: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "congestion_drops_interval": {"type": int}, + "global_link_status": {"type": bool}, + "storm_control": {"type": StormControl}, + "_custom_data": {"type": dict}, + } + congestion_drops_interval: int | None + """Logging interval in seconds.""" + global_link_status: bool | None + storm_control: StormControl + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + congestion_drops_interval: int | None | UndefinedType = Undefined, + global_link_status: bool | None | UndefinedType = Undefined, + storm_control: StormControl | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Event. + + + Subclass of AvdModel. + + Args: + congestion_drops_interval: Logging interval in seconds. + global_link_status: global_link_status + storm_control: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class LevelItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"facility": {"type": str}, "severity": {"type": str}, "_custom_data": {"type": dict}} + facility: str + severity: ( + Literal[ + "alerts", + "critical", + "debugging", + "emergencies", + "errors", + "informational", + "notifications", + "warnings", + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + ] + | None + ) + """ + Severity of facility. Below are the supported severities. + emergencies System is unusable + (severity=0) + alerts Immediate action needed (severity=1) + critical Critical + conditions (severity=2) + errors Error conditions (severity=3) + warnings Warning conditions (severity=4) + notifications Normal but significant + conditions (severity=5) + informational Informational messages (severity=6) + debugging + Debugging messages (severity=7) + <0-7> Severity level value + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + facility: str | UndefinedType = Undefined, + severity: Literal[ + "alerts", + "critical", + "debugging", + "emergencies", + "errors", + "informational", + "notifications", + "warnings", + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + ] + | None + | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LevelItem. + + + Subclass of AvdModel. + + Args: + facility: facility + severity: + Severity of facility. Below are the supported severities. + emergencies System is unusable + (severity=0) + alerts Immediate action needed (severity=1) + critical Critical + conditions (severity=2) + errors Error conditions (severity=3) + warnings Warning conditions (severity=4) + notifications Normal but significant + conditions (severity=5) + informational Informational messages (severity=6) + debugging + Debugging messages (severity=7) + <0-7> Severity level value + _custom_data: _custom_data + + """ + + class Level(AvdIndexedList[str, LevelItem]): + """Subclass of AvdIndexedList with `LevelItem` items. Primary key is `facility` (`str`).""" + + _primary_key: ClassVar[str] = "facility" + + Level._item_type = LevelItem + + _fields: ClassVar[dict] = { + "console": {"type": str}, + "monitor": {"type": str}, + "buffered": {"type": Buffered}, + "repeat_messages": {"type": bool}, + "trap": {"type": str}, + "synchronous": {"type": Synchronous}, + "format": {"type": Format}, + "facility": {"type": str}, + "source_interface": {"type": str}, + "vrfs": {"type": Vrfs}, + "policy": {"type": Policy}, + "event": {"type": Event}, + "level": {"type": Level}, + "_custom_data": {"type": dict}, + } + console: Literal["debugging", "informational", "notifications", "warnings", "errors", "critical", "alerts", "emergencies", "disabled"] | None + """Console logging severity level.""" + monitor: Literal["debugging", "informational", "notifications", "warnings", "errors", "critical", "alerts", "emergencies", "disabled"] | None + """Monitor logging severity level.""" + buffered: Buffered + """Subclass of AvdModel.""" + repeat_messages: bool | None + """Summarize concurrent repeat messages.""" + trap: Literal["alerts", "critical", "debugging", "emergencies", "errors", "informational", "notifications", "system", "warnings", "disabled"] | None + """Trap logging severity level.""" + synchronous: Synchronous + """Subclass of AvdModel.""" + format: Format + """Subclass of AvdModel.""" + facility: ( + Literal[ + "auth", + "cron", + "daemon", + "kern", + "local0", + "local1", + "local2", + "local3", + "local4", + "local5", + "local6", + "local7", + "lpr", + "mail", + "news", + "sys9", + "sys10", + "sys11", + "sys12", + "sys13", + "sys14", + "syslog", + "user", + "uucp", + ] + | None + ) + source_interface: str | None + """Source Interface Name.""" + vrfs: Vrfs + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + policy: Policy + """Subclass of AvdModel.""" + event: Event + """Subclass of AvdModel.""" + level: Level + """ + Configure logging severity. + + Subclass of AvdIndexedList with `LevelItem` items. Primary key is + `facility` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + console: Literal["debugging", "informational", "notifications", "warnings", "errors", "critical", "alerts", "emergencies", "disabled"] + | None + | UndefinedType = Undefined, + monitor: Literal["debugging", "informational", "notifications", "warnings", "errors", "critical", "alerts", "emergencies", "disabled"] + | None + | UndefinedType = Undefined, + buffered: Buffered | UndefinedType = Undefined, + repeat_messages: bool | None | UndefinedType = Undefined, + trap: Literal["alerts", "critical", "debugging", "emergencies", "errors", "informational", "notifications", "system", "warnings", "disabled"] + | None + | UndefinedType = Undefined, + synchronous: Synchronous | UndefinedType = Undefined, + format: Format | UndefinedType = Undefined, + facility: Literal[ + "auth", + "cron", + "daemon", + "kern", + "local0", + "local1", + "local2", + "local3", + "local4", + "local5", + "local6", + "local7", + "lpr", + "mail", + "news", + "sys9", + "sys10", + "sys11", + "sys12", + "sys13", + "sys14", + "syslog", + "user", + "uucp", + ] + | None + | UndefinedType = Undefined, + source_interface: str | None | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + policy: Policy | UndefinedType = Undefined, + event: Event | UndefinedType = Undefined, + level: Level | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Logging. + + + Subclass of AvdModel. + + Args: + console: Console logging severity level. + monitor: Monitor logging severity level. + buffered: Subclass of AvdModel. + repeat_messages: Summarize concurrent repeat messages. + trap: Trap logging severity level. + synchronous: Subclass of AvdModel. + format: Subclass of AvdModel. + facility: facility + source_interface: Source Interface Name. + vrfs: Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`). + policy: Subclass of AvdModel. + event: Subclass of AvdModel. + level: + Configure logging severity. + + Subclass of AvdIndexedList with `LevelItem` items. Primary key is + `facility` (`str`). + _custom_data: _custom_data + + """ + + class LoopbackInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class IpAddressSecondaries(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + IpAddressSecondaries._item_type = str + + class Mpls(AvdModel): + """Subclass of AvdModel.""" + + class Ldp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interface": {"type": bool}, "_custom_data": {"type": dict}} + interface: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, interface: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Ldp. + + + Subclass of AvdModel. + + Args: + interface: interface + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ldp": {"type": Ldp}, "_custom_data": {"type": dict}} + ldp: Ldp + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, ldp: Ldp | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Mpls. + + + Subclass of AvdModel. + + Args: + ldp: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class NodeSegment(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4_index": {"type": int}, "ipv6_index": {"type": int}, "_custom_data": {"type": dict}} + ipv4_index: int | None + ipv6_index: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4_index: int | None | UndefinedType = Undefined, + ipv6_index: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NodeSegment. + + + Subclass of AvdModel. + + Args: + ipv4_index: ipv4_index + ipv6_index: ipv6_index + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "description": {"type": str}, + "shutdown": {"type": bool}, + "vrf": {"type": str}, + "ip_address": {"type": str}, + "ip_address_secondaries": {"type": IpAddressSecondaries}, + "ipv6_enable": {"type": bool}, + "ipv6_address": {"type": str}, + "ip_proxy_arp": {"type": bool}, + "ospf_area": {"type": str}, + "mpls": {"type": Mpls}, + "isis_enable": {"type": str}, + "isis_bfd": {"type": bool}, + "isis_passive": {"type": bool}, + "isis_metric": {"type": int}, + "isis_network_point_to_point": {"type": bool}, + "node_segment": {"type": NodeSegment}, + "eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Loopback interface name e.g. "Loopback0".""" + description: str | None + shutdown: bool | None + vrf: str | None + """VRF name.""" + ip_address: str | None + """IPv4_address/Mask.""" + ip_address_secondaries: IpAddressSecondaries + """Subclass of AvdList with `str` items.""" + ipv6_enable: bool | None + ipv6_address: str | None + """IPv6_address/Mask.""" + ip_proxy_arp: bool | None + ospf_area: str | None + mpls: Mpls + """Subclass of AvdModel.""" + isis_enable: str | None + """ISIS instance name.""" + isis_bfd: bool | None + """Enable BFD for ISIS.""" + isis_passive: bool | None + isis_metric: int | None + isis_network_point_to_point: bool | None + node_segment: NodeSegment + """Subclass of AvdModel.""" + eos_cli: str | None + """EOS CLI rendered directly on the loopback interface in the final EOS configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + ip_address_secondaries: IpAddressSecondaries | UndefinedType = Undefined, + ipv6_enable: bool | None | UndefinedType = Undefined, + ipv6_address: str | None | UndefinedType = Undefined, + ip_proxy_arp: bool | None | UndefinedType = Undefined, + ospf_area: str | None | UndefinedType = Undefined, + mpls: Mpls | UndefinedType = Undefined, + isis_enable: str | None | UndefinedType = Undefined, + isis_bfd: bool | None | UndefinedType = Undefined, + isis_passive: bool | None | UndefinedType = Undefined, + isis_metric: int | None | UndefinedType = Undefined, + isis_network_point_to_point: bool | None | UndefinedType = Undefined, + node_segment: NodeSegment | UndefinedType = Undefined, + eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LoopbackInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: Loopback interface name e.g. "Loopback0". + description: description + shutdown: shutdown + vrf: VRF name. + ip_address: IPv4_address/Mask. + ip_address_secondaries: Subclass of AvdList with `str` items. + ipv6_enable: ipv6_enable + ipv6_address: IPv6_address/Mask. + ip_proxy_arp: ip_proxy_arp + ospf_area: ospf_area + mpls: Subclass of AvdModel. + isis_enable: ISIS instance name. + isis_bfd: Enable BFD for ISIS. + isis_passive: isis_passive + isis_metric: isis_metric + isis_network_point_to_point: isis_network_point_to_point + node_segment: Subclass of AvdModel. + eos_cli: EOS CLI rendered directly on the loopback interface in the final EOS configuration. + _custom_data: _custom_data + + """ + + class LoopbackInterfaces(AvdIndexedList[str, LoopbackInterfacesItem]): + """Subclass of AvdIndexedList with `LoopbackInterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + LoopbackInterfaces._item_type = LoopbackInterfacesItem + + class MacAccessListsItem(AvdModel): + """Subclass of AvdModel.""" + + class EntriesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"sequence": {"type": int}, "action": {"type": str}, "_custom_data": {"type": dict}} + sequence: int | None + action: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sequence: int | None | UndefinedType = Undefined, + action: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EntriesItem. + + + Subclass of AvdModel. + + Args: + sequence: sequence + action: action + _custom_data: _custom_data + + """ + + class Entries(AvdList[EntriesItem]): + """Subclass of AvdList with `EntriesItem` items.""" + + Entries._item_type = EntriesItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "counters_per_entry": {"type": bool}, "entries": {"type": Entries}, "_custom_data": {"type": dict}} + name: str + """MAC Access-list Name.""" + counters_per_entry: bool | None + entries: Entries + """Subclass of AvdList with `EntriesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + counters_per_entry: bool | None | UndefinedType = Undefined, + entries: Entries | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MacAccessListsItem. + + + Subclass of AvdModel. + + Args: + name: MAC Access-list Name. + counters_per_entry: counters_per_entry + entries: Subclass of AvdList with `EntriesItem` items. + _custom_data: _custom_data + + """ + + class MacAccessLists(AvdIndexedList[str, MacAccessListsItem]): + """Subclass of AvdIndexedList with `MacAccessListsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + MacAccessLists._item_type = MacAccessListsItem + + class MacAddressTable(AvdModel): + """Subclass of AvdModel.""" + + class NotificationHostFlap(AvdModel): + """Subclass of AvdModel.""" + + class Detection(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"window": {"type": int}, "moves": {"type": int}, "_custom_data": {"type": dict}} + window: int | None + moves: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + window: int | None | UndefinedType = Undefined, + moves: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Detection. + + + Subclass of AvdModel. + + Args: + window: window + moves: moves + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"logging": {"type": bool}, "detection": {"type": Detection}, "_custom_data": {"type": dict}} + logging: bool | None + detection: Detection + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + logging: bool | None | UndefinedType = Undefined, + detection: Detection | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NotificationHostFlap. + + + Subclass of AvdModel. + + Args: + logging: logging + detection: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"aging_time": {"type": int}, "notification_host_flap": {"type": NotificationHostFlap}, "_custom_data": {"type": dict}} + aging_time: int | None + """Aging time in seconds.""" + notification_host_flap: NotificationHostFlap + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + aging_time: int | None | UndefinedType = Undefined, + notification_host_flap: NotificationHostFlap | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MacAddressTable. + + + Subclass of AvdModel. + + Args: + aging_time: Aging time in seconds. + notification_host_flap: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MacSecurity(AvdModel): + """Subclass of AvdModel.""" + + class License(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"license_name": {"type": str}, "license_key": {"type": str}, "_custom_data": {"type": dict}} + license_name: str + license_key: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + license_name: str | UndefinedType = Undefined, + license_key: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + License. + + + Subclass of AvdModel. + + Args: + license_name: license_name + license_key: license_key + _custom_data: _custom_data + + """ + + class ProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class ConnectionKeysItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"id": {"type": str}, "encrypted_key": {"type": str}, "fallback": {"type": bool}, "_custom_data": {"type": dict}} + id: str + encrypted_key: str | None + fallback: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: str | UndefinedType = Undefined, + encrypted_key: str | None | UndefinedType = Undefined, + fallback: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ConnectionKeysItem. + + + Subclass of AvdModel. + + Args: + id: id + encrypted_key: encrypted_key + fallback: fallback + _custom_data: _custom_data + + """ + + class ConnectionKeys(AvdIndexedList[str, ConnectionKeysItem]): + """Subclass of AvdIndexedList with `ConnectionKeysItem` items. Primary key is `id` (`str`).""" + + _primary_key: ClassVar[str] = "id" + + ConnectionKeys._item_type = ConnectionKeysItem + + class Mka(AvdModel): + """Subclass of AvdModel.""" + + class Session(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"rekey_period": {"type": int}, "_custom_data": {"type": dict}} + rekey_period: int | None + """Rekey period in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, rekey_period: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Session. + + + Subclass of AvdModel. + + Args: + rekey_period: Rekey period in seconds. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"key_server_priority": {"type": int}, "session": {"type": Session}, "_custom_data": {"type": dict}} + key_server_priority: int | None + session: Session + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + key_server_priority: int | None | UndefinedType = Undefined, + session: Session | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Mka. + + + Subclass of AvdModel. + + Args: + key_server_priority: key_server_priority + session: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L2Protocols(AvdModel): + """Subclass of AvdModel.""" + + class EthernetFlowControl(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"mode": {"type": str}, "_custom_data": {"type": dict}} + mode: Literal["encrypt", "bypass"] + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, mode: Literal["encrypt", "bypass"] | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + EthernetFlowControl. + + + Subclass of AvdModel. + + Args: + mode: mode + _custom_data: _custom_data + + """ + + class Lldp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"mode": {"type": str}, "_custom_data": {"type": dict}} + mode: Literal["bypass", "bypass unauthorized"] + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["bypass", "bypass unauthorized"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Lldp. + + + Subclass of AvdModel. + + Args: + mode: mode + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ethernet_flow_control": {"type": EthernetFlowControl}, "lldp": {"type": Lldp}, "_custom_data": {"type": dict}} + ethernet_flow_control: EthernetFlowControl + """Subclass of AvdModel.""" + lldp: Lldp + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ethernet_flow_control: EthernetFlowControl | UndefinedType = Undefined, + lldp: Lldp | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L2Protocols. + + + Subclass of AvdModel. + + Args: + ethernet_flow_control: Subclass of AvdModel. + lldp: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class TrafficUnprotected(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"action": {"type": str}, "allow_active_sak": {"type": bool}, "_custom_data": {"type": dict}} + action: Literal["allow", "drop"] + """Allow/drop the transmit/receive of unprotected traffic.""" + allow_active_sak: bool | None + """Allow transmit/receive of encrypted traffic using operational SAK and block otherwise.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["allow", "drop"] | UndefinedType = Undefined, + allow_active_sak: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TrafficUnprotected. + + + Subclass of AvdModel. + + Args: + action: Allow/drop the transmit/receive of unprotected traffic. + allow_active_sak: Allow transmit/receive of encrypted traffic using operational SAK and block otherwise. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "cipher": {"type": str}, + "connection_keys": {"type": ConnectionKeys}, + "mka": {"type": Mka}, + "sci": {"type": bool}, + "l2_protocols": {"type": L2Protocols}, + "traffic_unprotected": {"type": TrafficUnprotected}, + "_custom_data": {"type": dict}, + } + name: str + """Profile-Name.""" + cipher: Literal["aes128-gcm", "aes128-gcm-xpn", "aes256-gcm", "aes256-gcm-xpn"] | None + connection_keys: ConnectionKeys + """Subclass of AvdIndexedList with `ConnectionKeysItem` items. Primary key is `id` (`str`).""" + mka: Mka + """Subclass of AvdModel.""" + sci: bool | None + l2_protocols: L2Protocols + """Subclass of AvdModel.""" + traffic_unprotected: TrafficUnprotected + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + cipher: Literal["aes128-gcm", "aes128-gcm-xpn", "aes256-gcm", "aes256-gcm-xpn"] | None | UndefinedType = Undefined, + connection_keys: ConnectionKeys | UndefinedType = Undefined, + mka: Mka | UndefinedType = Undefined, + sci: bool | None | UndefinedType = Undefined, + l2_protocols: L2Protocols | UndefinedType = Undefined, + traffic_unprotected: TrafficUnprotected | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ProfilesItem. + + + Subclass of AvdModel. + + Args: + name: Profile-Name. + cipher: cipher + connection_keys: Subclass of AvdIndexedList with `ConnectionKeysItem` items. Primary key is `id` (`str`). + mka: Subclass of AvdModel. + sci: sci + l2_protocols: Subclass of AvdModel. + traffic_unprotected: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Profiles(AvdIndexedList[str, ProfilesItem]): + """Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Profiles._item_type = ProfilesItem + + _fields: ClassVar[dict] = { + "license": {"type": License}, + "fips_restrictions": {"type": bool}, + "profiles": {"type": Profiles}, + "_custom_data": {"type": dict}, + } + license: License + """Subclass of AvdModel.""" + fips_restrictions: bool | None + profiles: Profiles + """Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + license: License | UndefinedType = Undefined, + fips_restrictions: bool | None | UndefinedType = Undefined, + profiles: Profiles | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MacSecurity. + + + Subclass of AvdModel. + + Args: + license: Subclass of AvdModel. + fips_restrictions: fips_restrictions + profiles: Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class Maintenance(AvdModel): + """Subclass of AvdModel.""" + + class InterfaceProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class RateMonitoring(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"load_interval": {"type": int}, "threshold": {"type": int}, "_custom_data": {"type": dict}} + load_interval: int | None + """Load Interval in Seconds.""" + threshold: int | None + """Threshold in kbps.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + load_interval: int | None | UndefinedType = Undefined, + threshold: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RateMonitoring. + + + Subclass of AvdModel. + + Args: + load_interval: Load Interval in Seconds. + threshold: Threshold in kbps. + _custom_data: _custom_data + + """ + + class Shutdown(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"max_delay": {"type": int}, "_custom_data": {"type": dict}} + max_delay: int | None + """Max delay in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, max_delay: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Shutdown. + + + Subclass of AvdModel. + + Args: + max_delay: Max delay in seconds. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "rate_monitoring": {"type": RateMonitoring}, + "shutdown": {"type": Shutdown}, + "_custom_data": {"type": dict}, + } + name: str + rate_monitoring: RateMonitoring + """Subclass of AvdModel.""" + shutdown: Shutdown + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + rate_monitoring: RateMonitoring | UndefinedType = Undefined, + shutdown: Shutdown | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + InterfaceProfilesItem. + + + Subclass of AvdModel. + + Args: + name: name + rate_monitoring: Subclass of AvdModel. + shutdown: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class InterfaceProfiles(AvdIndexedList[str, InterfaceProfilesItem]): + """Subclass of AvdIndexedList with `InterfaceProfilesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + InterfaceProfiles._item_type = InterfaceProfilesItem + + class BgpProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class Initiator(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"route_map_inout": {"type": str}, "_custom_data": {"type": dict}} + route_map_inout: str | None + """Route Map.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, route_map_inout: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Initiator. + + + Subclass of AvdModel. + + Args: + route_map_inout: Route Map. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"name": {"type": str}, "initiator": {"type": Initiator}, "_custom_data": {"type": dict}} + name: str + """BGP Profile Name.""" + initiator: Initiator + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + initiator: Initiator | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BgpProfilesItem. + + + Subclass of AvdModel. + + Args: + name: BGP Profile Name. + initiator: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class BgpProfiles(AvdIndexedList[str, BgpProfilesItem]): + """Subclass of AvdIndexedList with `BgpProfilesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + BgpProfiles._item_type = BgpProfilesItem + + class UnitProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class OnBoot(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"duration": {"type": int}, "_custom_data": {"type": dict}} + duration: int | None + """On-boot in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, duration: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + OnBoot. + + + Subclass of AvdModel. + + Args: + duration: On-boot in seconds. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"name": {"type": str}, "on_boot": {"type": OnBoot}, "_custom_data": {"type": dict}} + name: str + """Unit Profile Name.""" + on_boot: OnBoot + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + on_boot: OnBoot | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + UnitProfilesItem. + + + Subclass of AvdModel. + + Args: + name: Unit Profile Name. + on_boot: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class UnitProfiles(AvdIndexedList[str, UnitProfilesItem]): + """Subclass of AvdIndexedList with `UnitProfilesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + UnitProfiles._item_type = UnitProfilesItem + + class UnitsItem(AvdModel): + """Subclass of AvdModel.""" + + class Groups(AvdModel): + """Subclass of AvdModel.""" + + class BgpGroups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + BgpGroups._item_type = str + + class InterfaceGroups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + InterfaceGroups._item_type = str + + _fields: ClassVar[dict] = {"bgp_groups": {"type": BgpGroups}, "interface_groups": {"type": InterfaceGroups}, "_custom_data": {"type": dict}} + bgp_groups: BgpGroups + """Subclass of AvdList with `str` items.""" + interface_groups: InterfaceGroups + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + bgp_groups: BgpGroups | UndefinedType = Undefined, + interface_groups: InterfaceGroups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Groups. + + + Subclass of AvdModel. + + Args: + bgp_groups: Subclass of AvdList with `str` items. + interface_groups: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "quiesce": {"type": bool}, + "profile": {"type": str}, + "groups": {"type": Groups}, + "_custom_data": {"type": dict}, + } + name: str + """Unit Name.""" + quiesce: bool | None + profile: str | None + """Name of Unit Profile.""" + groups: Groups + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + quiesce: bool | None | UndefinedType = Undefined, + profile: str | None | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + UnitsItem. + + + Subclass of AvdModel. + + Args: + name: Unit Name. + quiesce: quiesce + profile: Name of Unit Profile. + groups: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Units(AvdIndexedList[str, UnitsItem]): + """Subclass of AvdIndexedList with `UnitsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Units._item_type = UnitsItem + + _fields: ClassVar[dict] = { + "default_interface_profile": {"type": str}, + "default_bgp_profile": {"type": str}, + "default_unit_profile": {"type": str}, + "interface_profiles": {"type": InterfaceProfiles}, + "bgp_profiles": {"type": BgpProfiles}, + "unit_profiles": {"type": UnitProfiles}, + "units": {"type": Units}, + "_custom_data": {"type": dict}, + } + default_interface_profile: str | None + """Name of default Interface Profile.""" + default_bgp_profile: str | None + """Name of default BGP Profile.""" + default_unit_profile: str | None + """Name of default Unit Profile.""" + interface_profiles: InterfaceProfiles + """Subclass of AvdIndexedList with `InterfaceProfilesItem` items. Primary key is `name` (`str`).""" + bgp_profiles: BgpProfiles + """Subclass of AvdIndexedList with `BgpProfilesItem` items. Primary key is `name` (`str`).""" + unit_profiles: UnitProfiles + """Subclass of AvdIndexedList with `UnitProfilesItem` items. Primary key is `name` (`str`).""" + units: Units + """Subclass of AvdIndexedList with `UnitsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + default_interface_profile: str | None | UndefinedType = Undefined, + default_bgp_profile: str | None | UndefinedType = Undefined, + default_unit_profile: str | None | UndefinedType = Undefined, + interface_profiles: InterfaceProfiles | UndefinedType = Undefined, + bgp_profiles: BgpProfiles | UndefinedType = Undefined, + unit_profiles: UnitProfiles | UndefinedType = Undefined, + units: Units | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Maintenance. + + + Subclass of AvdModel. + + Args: + default_interface_profile: Name of default Interface Profile. + default_bgp_profile: Name of default BGP Profile. + default_unit_profile: Name of default Unit Profile. + interface_profiles: Subclass of AvdIndexedList with `InterfaceProfilesItem` items. Primary key is `name` (`str`). + bgp_profiles: Subclass of AvdIndexedList with `BgpProfilesItem` items. Primary key is `name` (`str`). + unit_profiles: Subclass of AvdIndexedList with `UnitProfilesItem` items. Primary key is `name` (`str`). + units: Subclass of AvdIndexedList with `UnitsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class ManagementAccounts(AvdModel): + """Subclass of AvdModel.""" + + class Password(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"policy": {"type": str}, "_custom_data": {"type": dict}} + policy: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, policy: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Password. + + + Subclass of AvdModel. + + Args: + policy: policy + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"password": {"type": Password}, "_custom_data": {"type": dict}} + password: Password + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, password: Password | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + ManagementAccounts. + + + Subclass of AvdModel. + + Args: + password: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class ManagementApiGnmi(AvdModel): + """Subclass of AvdModel.""" + + class Transport(AvdModel): + """Subclass of AvdModel.""" + + class GrpcItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "ssl_profile": {"type": str}, + "vrf": {"type": str}, + "notification_timestamp": {"type": str}, + "ip_access_group": {"type": str}, + "port": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str + """Transport name.""" + ssl_profile: str | None + """SSL profile name.""" + vrf: str | None + """VRF name is optional.""" + notification_timestamp: Literal["send-time", "last-change-time"] | None + """ + Per the gNMI specification, the default timestamp field of a notification message is set to be + the + time at which the value of the underlying data source changes or when the reported event takes + place. + In order to facilitate integration in legacy environments oriented around polling style + operations, + an option to support overriding the timestamp field to the send-time is available from + EOS 4.27.0F. + """ + ip_access_group: str | None + """ACL name.""" + port: int | None + """ + GNMI port. + Make sure to update the control-plane ACL accordingly in order for the service to be + reachable by external applications. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + ssl_profile: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + notification_timestamp: Literal["send-time", "last-change-time"] | None | UndefinedType = Undefined, + ip_access_group: str | None | UndefinedType = Undefined, + port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GrpcItem. + + + Subclass of AvdModel. + + Args: + name: Transport name. + ssl_profile: SSL profile name. + vrf: VRF name is optional. + notification_timestamp: + Per the gNMI specification, the default timestamp field of a notification message is set to be + the + time at which the value of the underlying data source changes or when the reported event takes + place. + In order to facilitate integration in legacy environments oriented around polling style + operations, + an option to support overriding the timestamp field to the send-time is available from + EOS 4.27.0F. + ip_access_group: ACL name. + port: + GNMI port. + Make sure to update the control-plane ACL accordingly in order for the service to be + reachable by external applications. + _custom_data: _custom_data + + """ + + class Grpc(AvdIndexedList[str, GrpcItem]): + """Subclass of AvdIndexedList with `GrpcItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Grpc._item_type = GrpcItem + + class GrpcTunnelsItem(AvdModel): + """Subclass of AvdModel.""" + + class Destination(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"address": {"type": str}, "port": {"type": int}, "_custom_data": {"type": dict}} + address: str + """IP address or hostname.""" + port: int + """TCP Port.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + address: str | UndefinedType = Undefined, + port: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Destination. + + + Subclass of AvdModel. + + Args: + address: IP address or hostname. + port: TCP Port. + _custom_data: _custom_data + + """ + + class LocalInterface(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "port": {"type": int}, "_custom_data": {"type": dict}} + name: str + """Interface name.""" + port: int + """TCP Port.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + port: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LocalInterface. + + + Subclass of AvdModel. + + Args: + name: Interface name. + port: TCP Port. + _custom_data: _custom_data + + """ + + class Target(AvdModel): + """Subclass of AvdModel.""" + + class TargetIds(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + TargetIds._item_type = str + + _fields: ClassVar[dict] = {"use_serial_number": {"type": bool}, "target_ids": {"type": TargetIds}, "_custom_data": {"type": dict}} + use_serial_number: bool | None + """Use serial number as the Target ID.""" + target_ids: TargetIds + """ + Target IDs as a list. + + + Subclass of AvdList with `str` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + use_serial_number: bool | None | UndefinedType = Undefined, + target_ids: TargetIds | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Target. + + + Subclass of AvdModel. + + Args: + use_serial_number: Use serial number as the Target ID. + target_ids: + Target IDs as a list. + + + Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "shutdown": {"type": bool}, + "tunnel_ssl_profile": {"type": str}, + "gnmi_ssl_profile": {"type": str}, + "vrf": {"type": str}, + "destination": {"type": Destination}, + "local_interface": {"type": LocalInterface}, + "target": {"type": Target}, + "_custom_data": {"type": dict}, + } + name: str + """Transport name.""" + shutdown: bool | None + """Operational status of the gRPC tunnel.""" + tunnel_ssl_profile: str | None + """Tunnel SSL profile name.""" + gnmi_ssl_profile: str | None + """gNMI SSL profile name.""" + vrf: str | None + """VRF name.""" + destination: Destination + """Subclass of AvdModel.""" + local_interface: LocalInterface + """Subclass of AvdModel.""" + target: Target + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + tunnel_ssl_profile: str | None | UndefinedType = Undefined, + gnmi_ssl_profile: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + destination: Destination | UndefinedType = Undefined, + local_interface: LocalInterface | UndefinedType = Undefined, + target: Target | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GrpcTunnelsItem. + + + Subclass of AvdModel. + + Args: + name: Transport name. + shutdown: Operational status of the gRPC tunnel. + tunnel_ssl_profile: Tunnel SSL profile name. + gnmi_ssl_profile: gNMI SSL profile name. + vrf: VRF name. + destination: Subclass of AvdModel. + local_interface: Subclass of AvdModel. + target: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class GrpcTunnels(AvdIndexedList[str, GrpcTunnelsItem]): + """Subclass of AvdIndexedList with `GrpcTunnelsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + GrpcTunnels._item_type = GrpcTunnelsItem + + _fields: ClassVar[dict] = {"grpc": {"type": Grpc}, "grpc_tunnels": {"type": GrpcTunnels}, "_custom_data": {"type": dict}} + grpc: Grpc + """Subclass of AvdIndexedList with `GrpcItem` items. Primary key is `name` (`str`).""" + grpc_tunnels: GrpcTunnels + """Subclass of AvdIndexedList with `GrpcTunnelsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + grpc: Grpc | UndefinedType = Undefined, + grpc_tunnels: GrpcTunnels | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Transport. + + + Subclass of AvdModel. + + Args: + grpc: Subclass of AvdIndexedList with `GrpcItem` items. Primary key is `name` (`str`). + grpc_tunnels: Subclass of AvdIndexedList with `GrpcTunnelsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"provider": {"type": str, "default": "eos-native"}, "transport": {"type": Transport}, "_custom_data": {"type": dict}} + provider: str + """Default value: `"eos-native"`""" + transport: Transport + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + provider: str | UndefinedType = Undefined, + transport: Transport | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ManagementApiGnmi. + + + Subclass of AvdModel. + + Args: + provider: provider + transport: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class ManagementApiHttp(AvdModel): + """Subclass of AvdModel.""" + + class EnableVrfsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "access_group": {"type": str}, "ipv6_access_group": {"type": str}, "_custom_data": {"type": dict}} + name: str + """VRF Name.""" + access_group: str | None + """Standard IPv4 ACL name.""" + ipv6_access_group: str | None + """Standard IPv6 ACL name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + access_group: str | None | UndefinedType = Undefined, + ipv6_access_group: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EnableVrfsItem. + + + Subclass of AvdModel. + + Args: + name: VRF Name. + access_group: Standard IPv4 ACL name. + ipv6_access_group: Standard IPv6 ACL name. + _custom_data: _custom_data + + """ + + class EnableVrfs(AvdIndexedList[str, EnableVrfsItem]): + """Subclass of AvdIndexedList with `EnableVrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + EnableVrfs._item_type = EnableVrfsItem + + class ProtocolHttpsCertificate(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"certificate": {"type": str}, "private_key": {"type": str}, "_custom_data": {"type": dict}} + certificate: str | None + """Name of certificate; private key must also be specified.""" + private_key: str | None + """Name of private key; certificate must also be specified.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + certificate: str | None | UndefinedType = Undefined, + private_key: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ProtocolHttpsCertificate. + + + Subclass of AvdModel. + + Args: + certificate: Name of certificate; private key must also be specified. + private_key: Name of private key; certificate must also be specified. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enable_http": {"type": bool}, + "enable_https": {"type": bool}, + "https_ssl_profile": {"type": str}, + "default_services": {"type": bool}, + "enable_vrfs": {"type": EnableVrfs}, + "protocol_https_certificate": {"type": ProtocolHttpsCertificate}, + "_custom_data": {"type": dict}, + } + enable_http: bool | None + enable_https: bool | None + https_ssl_profile: str | None + """SSL Profile Name.""" + default_services: bool | None + """Enable default services: capi-doc and tapagg.""" + enable_vrfs: EnableVrfs + """Subclass of AvdIndexedList with `EnableVrfsItem` items. Primary key is `name` (`str`).""" + protocol_https_certificate: ProtocolHttpsCertificate + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enable_http: bool | None | UndefinedType = Undefined, + enable_https: bool | None | UndefinedType = Undefined, + https_ssl_profile: str | None | UndefinedType = Undefined, + default_services: bool | None | UndefinedType = Undefined, + enable_vrfs: EnableVrfs | UndefinedType = Undefined, + protocol_https_certificate: ProtocolHttpsCertificate | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ManagementApiHttp. + + + Subclass of AvdModel. + + Args: + enable_http: enable_http + enable_https: enable_https + https_ssl_profile: SSL Profile Name. + default_services: Enable default services: capi-doc and tapagg. + enable_vrfs: Subclass of AvdIndexedList with `EnableVrfsItem` items. Primary key is `name` (`str`). + protocol_https_certificate: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class ManagementApiModels(AvdModel): + """Subclass of AvdModel.""" + + class ProvidersItem(AvdModel): + """Subclass of AvdModel.""" + + class PathsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"path": {"type": str}, "disabled": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + path: str | None + disabled: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + path: str | None | UndefinedType = Undefined, + disabled: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PathsItem. + + + Subclass of AvdModel. + + Args: + path: path + disabled: disabled + _custom_data: _custom_data + + """ + + class Paths(AvdList[PathsItem]): + """Subclass of AvdList with `PathsItem` items.""" + + Paths._item_type = PathsItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "paths": {"type": Paths}, "_custom_data": {"type": dict}} + name: Literal["sysdb", "smash"] | None + paths: Paths + """Subclass of AvdList with `PathsItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: Literal["sysdb", "smash"] | None | UndefinedType = Undefined, + paths: Paths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ProvidersItem. + + + Subclass of AvdModel. + + Args: + name: name + paths: Subclass of AvdList with `PathsItem` items. + _custom_data: _custom_data + + """ + + class Providers(AvdList[ProvidersItem]): + """Subclass of AvdList with `ProvidersItem` items.""" + + Providers._item_type = ProvidersItem + + _fields: ClassVar[dict] = {"providers": {"type": Providers}, "_custom_data": {"type": dict}} + providers: Providers + """Subclass of AvdList with `ProvidersItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, providers: Providers | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + ManagementApiModels. + + + Subclass of AvdModel. + + Args: + providers: Subclass of AvdList with `ProvidersItem` items. + _custom_data: _custom_data + + """ + + class ManagementConsole(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"idle_timeout": {"type": int}, "_custom_data": {"type": dict}} + idle_timeout: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, idle_timeout: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + ManagementConsole. + + + Subclass of AvdModel. + + Args: + idle_timeout: idle_timeout + _custom_data: _custom_data + + """ + + class ManagementCvx(AvdModel): + """Subclass of AvdModel.""" + + class ServerHosts(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + ServerHosts._item_type = str + + _fields: ClassVar[dict] = { + "shutdown": {"type": bool}, + "server_hosts": {"type": ServerHosts}, + "source_interface": {"type": str}, + "vrf": {"type": str}, + "_custom_data": {"type": dict}, + } + shutdown: bool | None + server_hosts: ServerHosts + """Subclass of AvdList with `str` items.""" + source_interface: str | None + """Interface name.""" + vrf: str | None + """VRF Name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + shutdown: bool | None | UndefinedType = Undefined, + server_hosts: ServerHosts | UndefinedType = Undefined, + source_interface: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ManagementCvx. + + + Subclass of AvdModel. + + Args: + shutdown: shutdown + server_hosts: Subclass of AvdList with `str` items. + source_interface: Interface name. + vrf: VRF Name. + _custom_data: _custom_data + + """ + + class ManagementDefaults(AvdModel): + """Subclass of AvdModel.""" + + class Secret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"hash": {"type": str}, "_custom_data": {"type": dict}} + hash: Literal["md5", "sha512"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, hash: Literal["md5", "sha512"] | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Secret. + + + Subclass of AvdModel. + + Args: + hash: hash + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"secret": {"type": Secret}, "_custom_data": {"type": dict}} + secret: Secret + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, secret: Secret | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + ManagementDefaults. + + + Subclass of AvdModel. + + Args: + secret: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class ManagementInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Lldp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"transmit": {"type": bool}, "receive": {"type": bool}, "ztp_vlan": {"type": int}, "_custom_data": {"type": dict}} + transmit: bool | None + receive: bool | None + ztp_vlan: int | None + """ZTP vlan number.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + transmit: bool | None | UndefinedType = Undefined, + receive: bool | None | UndefinedType = Undefined, + ztp_vlan: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Lldp. + + + Subclass of AvdModel. + + Args: + transmit: transmit + receive: receive + ztp_vlan: ZTP vlan number. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "description": {"type": str}, + "shutdown": {"type": bool}, + "speed": {"type": str}, + "mtu": {"type": int}, + "vrf": {"type": str}, + "ip_address": {"type": str}, + "ipv6_enable": {"type": bool}, + "ipv6_address": {"type": str}, + "type": {"type": str, "default": "oob"}, + "gateway": {"type": str}, + "ipv6_gateway": {"type": str}, + "mac_address": {"type": str}, + "lldp": {"type": Lldp}, + "eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Management Interface Name.""" + description: str | None + shutdown: bool | None + speed: str | None + """ + Speed should be set in the format `` or `forced ` or `auto + `. + """ + mtu: int | None + vrf: str | None + """VRF Name.""" + ip_address: str | None + """IPv4_address/Mask.""" + ipv6_enable: bool | None + ipv6_address: str | None + """IPv6_address/Mask.""" + type: Literal["oob", "inband"] + """ + For documentation purposes only. + + Default value: `"oob"` + """ + gateway: str | None + """IPv4 address of default gateway in management VRF.""" + ipv6_gateway: str | None + """IPv6 address of default gateway in management VRF.""" + mac_address: str | None + """MAC address.""" + lldp: Lldp + """Subclass of AvdModel.""" + eos_cli: str | None + """Multiline EOS CLI rendered directly on the management interface in the final EOS configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + speed: str | None | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + ipv6_enable: bool | None | UndefinedType = Undefined, + ipv6_address: str | None | UndefinedType = Undefined, + type: Literal["oob", "inband"] | UndefinedType = Undefined, + gateway: str | None | UndefinedType = Undefined, + ipv6_gateway: str | None | UndefinedType = Undefined, + mac_address: str | None | UndefinedType = Undefined, + lldp: Lldp | UndefinedType = Undefined, + eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ManagementInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: Management Interface Name. + description: description + shutdown: shutdown + speed: + Speed should be set in the format `` or `forced ` or `auto + `. + mtu: mtu + vrf: VRF Name. + ip_address: IPv4_address/Mask. + ipv6_enable: ipv6_enable + ipv6_address: IPv6_address/Mask. + type: For documentation purposes only. + gateway: IPv4 address of default gateway in management VRF. + ipv6_gateway: IPv6 address of default gateway in management VRF. + mac_address: MAC address. + lldp: Subclass of AvdModel. + eos_cli: Multiline EOS CLI rendered directly on the management interface in the final EOS configuration. + _custom_data: _custom_data + + """ + + class ManagementInterfaces(AvdIndexedList[str, ManagementInterfacesItem]): + """Subclass of AvdIndexedList with `ManagementInterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + ManagementInterfaces._item_type = ManagementInterfacesItem + + class ManagementSecurity(AvdModel): + """Subclass of AvdModel.""" + + class EntropySources(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hardware": {"type": bool}, + "haveged": {"type": bool}, + "cpu_jitter": {"type": bool}, + "hardware_exclusive": {"type": bool}, + "_custom_data": {"type": dict}, + } + hardware: bool | None + """Use a hardware based source.""" + haveged: bool | None + """Use the HAVEGE algorithm.""" + cpu_jitter: bool | None + """Use the Jitter RNG algorithm of a CPU based source.""" + hardware_exclusive: bool | None + """Only use entropy from the hardware source.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hardware: bool | None | UndefinedType = Undefined, + haveged: bool | None | UndefinedType = Undefined, + cpu_jitter: bool | None | UndefinedType = Undefined, + hardware_exclusive: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EntropySources. + + + Subclass of AvdModel. + + Args: + hardware: Use a hardware based source. + haveged: Use the HAVEGE algorithm. + cpu_jitter: Use the Jitter RNG algorithm of a CPU based source. + hardware_exclusive: Only use entropy from the hardware source. + _custom_data: _custom_data + + """ + + class Password(AvdModel): + """Subclass of AvdModel.""" + + class PoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + class Minimum(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "digits": {"type": int}, + "length": {"type": int}, + "lower": {"type": int}, + "special": {"type": int}, + "upper": {"type": int}, + "_custom_data": {"type": dict}, + } + digits: int | None + length: int | None + lower: int | None + special: int | None + upper: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + digits: int | None | UndefinedType = Undefined, + length: int | None | UndefinedType = Undefined, + lower: int | None | UndefinedType = Undefined, + special: int | None | UndefinedType = Undefined, + upper: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Minimum. + + + Subclass of AvdModel. + + Args: + digits: digits + length: length + lower: lower + special: special + upper: upper + _custom_data: _custom_data + + """ + + class Maximum(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"repetitive": {"type": int}, "sequential": {"type": int}, "_custom_data": {"type": dict}} + repetitive: int | None + sequential: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + repetitive: int | None | UndefinedType = Undefined, + sequential: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Maximum. + + + Subclass of AvdModel. + + Args: + repetitive: repetitive + sequential: sequential + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"name": {"type": str}, "minimum": {"type": Minimum}, "maximum": {"type": Maximum}, "_custom_data": {"type": dict}} + name: str + minimum: Minimum + """Subclass of AvdModel.""" + maximum: Maximum + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + minimum: Minimum | UndefinedType = Undefined, + maximum: Maximum | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PoliciesItem. + + + Subclass of AvdModel. + + Args: + name: name + minimum: Subclass of AvdModel. + maximum: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Policies(AvdIndexedList[str, PoliciesItem]): + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Policies._item_type = PoliciesItem + + _fields: ClassVar[dict] = { + "minimum_length": {"type": int}, + "encryption_key_common": {"type": bool}, + "encryption_reversible": {"type": str}, + "policies": {"type": Policies}, + "_custom_data": {"type": dict}, + } + minimum_length: int | None + encryption_key_common: bool | None + encryption_reversible: str | None + policies: Policies + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + minimum_length: int | None | UndefinedType = Undefined, + encryption_key_common: bool | None | UndefinedType = Undefined, + encryption_reversible: str | None | UndefinedType = Undefined, + policies: Policies | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Password. + + + Subclass of AvdModel. + + Args: + minimum_length: minimum_length + encryption_key_common: encryption_key_common + encryption_reversible: encryption_reversible + policies: Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class SslProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class TrustCertificate(AvdModel): + """Subclass of AvdModel.""" + + class Certificates(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Certificates._item_type = str + + class Requirement(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"basic_constraint_ca": {"type": bool}, "hostname_fqdn": {"type": bool}, "_custom_data": {"type": dict}} + basic_constraint_ca: bool | None + hostname_fqdn: bool | None + """Enforce hostname to be FQDN without wildcard.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + basic_constraint_ca: bool | None | UndefinedType = Undefined, + hostname_fqdn: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Requirement. + + + Subclass of AvdModel. + + Args: + basic_constraint_ca: basic_constraint_ca + hostname_fqdn: Enforce hostname to be FQDN without wildcard. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "certificates": {"type": Certificates}, + "requirement": {"type": Requirement}, + "policy_expiry_date_ignore": {"type": bool}, + "system": {"type": bool}, + "_custom_data": {"type": dict}, + } + certificates: Certificates + """ + List of trust certificate names. + Examples: + - test1.crt + - test2.crt + + + Subclass of AvdList with + `str` items. + """ + requirement: Requirement + """Subclass of AvdModel.""" + policy_expiry_date_ignore: bool | None + system: bool | None + """Use system-supplied trust certificates.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + certificates: Certificates | UndefinedType = Undefined, + requirement: Requirement | UndefinedType = Undefined, + policy_expiry_date_ignore: bool | None | UndefinedType = Undefined, + system: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TrustCertificate. + + + Subclass of AvdModel. + + Args: + certificates: + List of trust certificate names. + Examples: # fmt: skip + - test1.crt + - test2.crt + + + Subclass of AvdList with + `str` items. + requirement: Subclass of AvdModel. + policy_expiry_date_ignore: policy_expiry_date_ignore + system: Use system-supplied trust certificates. + _custom_data: _custom_data + + """ + + class ChainCertificate(AvdModel): + """Subclass of AvdModel.""" + + class Certificates(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Certificates._item_type = str + + class Requirement(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"basic_constraint_ca": {"type": bool}, "include_root_ca": {"type": bool}, "_custom_data": {"type": dict}} + basic_constraint_ca: bool | None + include_root_ca: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + basic_constraint_ca: bool | None | UndefinedType = Undefined, + include_root_ca: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Requirement. + + + Subclass of AvdModel. + + Args: + basic_constraint_ca: basic_constraint_ca + include_root_ca: include_root_ca + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"certificates": {"type": Certificates}, "requirement": {"type": Requirement}, "_custom_data": {"type": dict}} + certificates: Certificates + """ + List of chain certificate names. + Examples: + - chain1.crt + - chain2.crt + + + Subclass of AvdList with + `str` items. + """ + requirement: Requirement + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + certificates: Certificates | UndefinedType = Undefined, + requirement: Requirement | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ChainCertificate. + + + Subclass of AvdModel. + + Args: + certificates: + List of chain certificate names. + Examples: # fmt: skip + - chain1.crt + - chain2.crt + + + Subclass of AvdList with + `str` items. + requirement: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Certificate(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"file": {"type": str}, "key": {"type": str}, "_custom_data": {"type": dict}} + file: str | None + key: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + file: str | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Certificate. + + + Subclass of AvdModel. + + Args: + file: file + key: key + _custom_data: _custom_data + + """ + + class CertificateRevocationLists(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + CertificateRevocationLists._item_type = str + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "tls_versions": {"type": str}, + "cipher_list": {"type": str}, + "trust_certificate": {"type": TrustCertificate}, + "chain_certificate": {"type": ChainCertificate}, + "certificate": {"type": Certificate}, + "certificate_revocation_lists": {"type": CertificateRevocationLists}, + "_custom_data": {"type": dict}, + } + name: str | None + tls_versions: str | None + """ + List of allowed TLS versions as string. + Examples: + - "1.0" + - "1.0 1.1" + """ + cipher_list: str | None + """ + cipher_list syntax follows the openssl cipher strings format. + Colon (:) separated list of allowed + ciphers as a string. + """ + trust_certificate: TrustCertificate + """Subclass of AvdModel.""" + chain_certificate: ChainCertificate + """Subclass of AvdModel.""" + certificate: Certificate + """Subclass of AvdModel.""" + certificate_revocation_lists: CertificateRevocationLists + """ + List of CRLs (Certificate Revocation List). + If specified, one CRL needs to be provided for every + certificate in the chain, even if the revocation list in the CRL is empty. + + + Subclass of AvdList + with `str` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + tls_versions: str | None | UndefinedType = Undefined, + cipher_list: str | None | UndefinedType = Undefined, + trust_certificate: TrustCertificate | UndefinedType = Undefined, + chain_certificate: ChainCertificate | UndefinedType = Undefined, + certificate: Certificate | UndefinedType = Undefined, + certificate_revocation_lists: CertificateRevocationLists | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SslProfilesItem. + + + Subclass of AvdModel. + + Args: + name: name + tls_versions: + List of allowed TLS versions as string. + Examples: # fmt: skip + - "1.0" + - "1.0 1.1" + cipher_list: + cipher_list syntax follows the openssl cipher strings format. + Colon (:) separated list of allowed + ciphers as a string. + trust_certificate: Subclass of AvdModel. + chain_certificate: Subclass of AvdModel. + certificate: Subclass of AvdModel. + certificate_revocation_lists: + List of CRLs (Certificate Revocation List). + If specified, one CRL needs to be provided for every + certificate in the chain, even if the revocation list in the CRL is empty. + + + Subclass of AvdList + with `str` items. + _custom_data: _custom_data + + """ + + class SslProfiles(AvdList[SslProfilesItem]): + """Subclass of AvdList with `SslProfilesItem` items.""" + + SslProfiles._item_type = SslProfilesItem + + class SharedSecretProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class SecretsItem(AvdModel): + """Subclass of AvdModel.""" + + class ReceiveLifetime(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "infinite": {"type": bool}, + "start_date_time": {"type": str}, + "end_date_time": {"type": str}, + "_custom_data": {"type": dict}, + } + infinite: bool | None + start_date_time: str | None + """ + Start date and time of lifetime of the secret. End date should be greater than start date. + Formats + supported: + 1. mm/dd/yyyy hh:mm:ss + 2. yyyy-mm-dd hh:mm:ss + e.g 2024-12-20 10:00:00 + """ + end_date_time: str | None + """ + End date and time of lifetime of the secret. End date should be greater than start date. + Formats + supported: + 1. mm/dd/yyyy hh:mm:ss + 2. yyyy-mm-dd hh:mm:ss + e.g 2024-12-20 10:00:00 + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + infinite: bool | None | UndefinedType = Undefined, + start_date_time: str | None | UndefinedType = Undefined, + end_date_time: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ReceiveLifetime. + + + Subclass of AvdModel. + + Args: + infinite: infinite + start_date_time: + Start date and time of lifetime of the secret. End date should be greater than start date. + Formats + supported: + 1. mm/dd/yyyy hh:mm:ss + 2. yyyy-mm-dd hh:mm:ss + e.g 2024-12-20 10:00:00 + end_date_time: + End date and time of lifetime of the secret. End date should be greater than start date. + Formats + supported: + 1. mm/dd/yyyy hh:mm:ss + 2. yyyy-mm-dd hh:mm:ss + e.g 2024-12-20 10:00:00 + _custom_data: _custom_data + + """ + + class TransmitLifetime(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "infinite": {"type": bool}, + "start_date_time": {"type": str}, + "end_date_time": {"type": str}, + "_custom_data": {"type": dict}, + } + infinite: bool | None + start_date_time: str | None + """ + Start date and time of lifetime of the secret. End date should be greater than start date. + Formats + supported: + 1. mm/dd/yyyy hh:mm:ss + 2. yyyy-mm-dd hh:mm:ss + e.g 2024-12-20 10:00:00 + """ + end_date_time: str | None + """ + End date and time of lifetime of the secret. End date should be greater than start date. + Formats + supported: + 1. mm/dd/yyyy hh:mm:ss + 2. yyyy-mm-dd hh:mm:ss + e.g 2024-12-20 10:00:00 + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + infinite: bool | None | UndefinedType = Undefined, + start_date_time: str | None | UndefinedType = Undefined, + end_date_time: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TransmitLifetime. + + + Subclass of AvdModel. + + Args: + infinite: infinite + start_date_time: + Start date and time of lifetime of the secret. End date should be greater than start date. + Formats + supported: + 1. mm/dd/yyyy hh:mm:ss + 2. yyyy-mm-dd hh:mm:ss + e.g 2024-12-20 10:00:00 + end_date_time: + End date and time of lifetime of the secret. End date should be greater than start date. + Formats + supported: + 1. mm/dd/yyyy hh:mm:ss + 2. yyyy-mm-dd hh:mm:ss + e.g 2024-12-20 10:00:00 + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "secret": {"type": str}, + "secret_type": {"type": str, "default": "7"}, + "receive_lifetime": {"type": ReceiveLifetime}, + "transmit_lifetime": {"type": TransmitLifetime}, + "local_time": {"type": bool}, + "_custom_data": {"type": dict}, + } + name: str + secret: str + secret_type: Literal["0", "7", "8a"] + """Default value: `"7"`""" + receive_lifetime: ReceiveLifetime + """Subclass of AvdModel.""" + transmit_lifetime: TransmitLifetime + """Subclass of AvdModel.""" + local_time: bool | None + """Configuring secret using the local timezone from system clock. Default is UTC.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + secret: str | UndefinedType = Undefined, + secret_type: Literal["0", "7", "8a"] | UndefinedType = Undefined, + receive_lifetime: ReceiveLifetime | UndefinedType = Undefined, + transmit_lifetime: TransmitLifetime | UndefinedType = Undefined, + local_time: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SecretsItem. + + + Subclass of AvdModel. + + Args: + name: name + secret: secret + secret_type: secret_type + receive_lifetime: Subclass of AvdModel. + transmit_lifetime: Subclass of AvdModel. + local_time: Configuring secret using the local timezone from system clock. Default is UTC. + _custom_data: _custom_data + + """ + + class Secrets(AvdIndexedList[str, SecretsItem]): + """Subclass of AvdIndexedList with `SecretsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Secrets._item_type = SecretsItem + + _fields: ClassVar[dict] = {"profile": {"type": str}, "secrets": {"type": Secrets}, "_custom_data": {"type": dict}} + profile: str + secrets: Secrets + """Subclass of AvdIndexedList with `SecretsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + secrets: Secrets | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SharedSecretProfilesItem. + + + Subclass of AvdModel. + + Args: + profile: profile + secrets: Subclass of AvdIndexedList with `SecretsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class SharedSecretProfiles(AvdIndexedList[str, SharedSecretProfilesItem]): + """Subclass of AvdIndexedList with `SharedSecretProfilesItem` items. Primary key is `profile` (`str`).""" + + _primary_key: ClassVar[str] = "profile" + + SharedSecretProfiles._item_type = SharedSecretProfilesItem + + _fields: ClassVar[dict] = { + "entropy_sources": {"type": EntropySources}, + "password": {"type": Password}, + "ssl_profiles": {"type": SslProfiles}, + "shared_secret_profiles": {"type": SharedSecretProfiles}, + "_custom_data": {"type": dict}, + } + entropy_sources: EntropySources + """ + Source of entropy. + + Subclass of AvdModel. + """ + password: Password + """Subclass of AvdModel.""" + ssl_profiles: SslProfiles + """Subclass of AvdList with `SslProfilesItem` items.""" + shared_secret_profiles: SharedSecretProfiles + """Subclass of AvdIndexedList with `SharedSecretProfilesItem` items. Primary key is `profile` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + entropy_sources: EntropySources | UndefinedType = Undefined, + password: Password | UndefinedType = Undefined, + ssl_profiles: SslProfiles | UndefinedType = Undefined, + shared_secret_profiles: SharedSecretProfiles | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ManagementSecurity. + + + Subclass of AvdModel. + + Args: + entropy_sources: + Source of entropy. + + Subclass of AvdModel. + password: Subclass of AvdModel. + ssl_profiles: Subclass of AvdList with `SslProfilesItem` items. + shared_secret_profiles: Subclass of AvdIndexedList with `SharedSecretProfilesItem` items. Primary key is `profile` (`str`). + _custom_data: _custom_data + + """ + + class ManagementSsh(AvdModel): + """Subclass of AvdModel.""" + + class Authentication(AvdModel): + """Subclass of AvdModel.""" + + class Protocols(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Protocols._item_type = str + + _fields: ClassVar[dict] = {"empty_passwords": {"type": str}, "protocols": {"type": Protocols}, "_custom_data": {"type": dict}} + empty_passwords: Literal["auto", "deny", "permit"] | None + """Permit or deny empty passwords for SSH authentication.""" + protocols: Protocols + """ + Allowed SSH authentication methods. + + Subclass of AvdList with `str` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + empty_passwords: Literal["auto", "deny", "permit"] | None | UndefinedType = Undefined, + protocols: Protocols | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Authentication. + + + Subclass of AvdModel. + + Args: + empty_passwords: Permit or deny empty passwords for SSH authentication. + protocols: + Allowed SSH authentication methods. + + Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class AccessGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + """Standard ACL Name.""" + vrf: str | None + """VRF Name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AccessGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Standard ACL Name. + vrf: VRF Name. + _custom_data: _custom_data + + """ + + class AccessGroups(AvdList[AccessGroupsItem]): + """Subclass of AvdList with `AccessGroupsItem` items.""" + + AccessGroups._item_type = AccessGroupsItem + + class Ipv6AccessGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + """Standard ACL Name.""" + vrf: str | None + """VRF Name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6AccessGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Standard ACL Name. + vrf: VRF Name. + _custom_data: _custom_data + + """ + + class Ipv6AccessGroups(AvdList[Ipv6AccessGroupsItem]): + """Subclass of AvdList with `Ipv6AccessGroupsItem` items.""" + + Ipv6AccessGroups._item_type = Ipv6AccessGroupsItem + + class Cipher(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Cipher._item_type = str + + class KeyExchange(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + KeyExchange._item_type = str + + class Mac(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Mac._item_type = str + + class Hostkey(AvdModel): + """Subclass of AvdModel.""" + + class Server(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Server._item_type = str + + _fields: ClassVar[dict] = { + "server": {"type": Server}, + "server_cert": {"type": str}, + "client_strict_checking": {"type": bool}, + "_custom_data": {"type": dict}, + } + server: Server + """ + SSH host key settings. + + Subclass of AvdList with `str` items. + """ + server_cert: str | None + """Configure switch's hostkey cert file.""" + client_strict_checking: bool | None + """Enforce strict host key checking.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + server: Server | UndefinedType = Undefined, + server_cert: str | None | UndefinedType = Undefined, + client_strict_checking: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Hostkey. + + + Subclass of AvdModel. + + Args: + server: + SSH host key settings. + + Subclass of AvdList with `str` items. + server_cert: Configure switch's hostkey cert file. + client_strict_checking: Enforce strict host key checking. + _custom_data: _custom_data + + """ + + class Connection(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"limit": {"type": int}, "per_host": {"type": int}, "_custom_data": {"type": dict}} + limit: int | None + """Maximum total number of SSH sessions to device.""" + per_host: int | None + """Maximum number of SSH sessions to device from a single host.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + limit: int | None | UndefinedType = Undefined, + per_host: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Connection. + + + Subclass of AvdModel. + + Args: + limit: Maximum total number of SSH sessions to device. + per_host: Maximum number of SSH sessions to device from a single host. + _custom_data: _custom_data + + """ + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "enable": {"type": bool}, "_custom_data": {"type": dict}} + name: str + """VRF Name.""" + enable: bool | None + """Enable SSH in VRF.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + enable: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: VRF Name. + enable: Enable SSH in VRF. + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + class ClientAlive(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"count_max": {"type": int}, "interval": {"type": int}, "_custom_data": {"type": dict}} + count_max: int | None + """ + Number of keep-alive packets that can be sent without a response before the connection is assumed + dead. + """ + interval: int | None + """Time period (in seconds) to send SSH keep-alive packets.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + count_max: int | None | UndefinedType = Undefined, + interval: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ClientAlive. + + + Subclass of AvdModel. + + Args: + count_max: + Number of keep-alive packets that can be sent without a response before the connection is assumed + dead. + interval: Time period (in seconds) to send SSH keep-alive packets. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "authentication": {"type": Authentication}, + "access_groups": {"type": AccessGroups}, + "ipv6_access_groups": {"type": Ipv6AccessGroups}, + "idle_timeout": {"type": int}, + "cipher": {"type": Cipher}, + "key_exchange": {"type": KeyExchange}, + "mac": {"type": Mac}, + "fips_restrictions": {"type": bool}, + "hostkey": {"type": Hostkey}, + "enable": {"type": bool}, + "connection": {"type": Connection}, + "vrfs": {"type": Vrfs}, + "log_level": {"type": str}, + "client_alive": {"type": ClientAlive}, + "_custom_data": {"type": dict}, + } + authentication: Authentication + """Subclass of AvdModel.""" + access_groups: AccessGroups + """Subclass of AvdList with `AccessGroupsItem` items.""" + ipv6_access_groups: Ipv6AccessGroups + """Subclass of AvdList with `Ipv6AccessGroupsItem` items.""" + idle_timeout: int | None + """Idle timeout in minutes.""" + cipher: Cipher + """ + Cryptographic ciphers for SSH to use. + + Subclass of AvdList with `str` items. + """ + key_exchange: KeyExchange + """ + Cryptographic key exchange methods for SSH to use. + + Subclass of AvdList with `str` items. + """ + mac: Mac + """ + Cryptographic MAC algorithms for SSH to use. + + Subclass of AvdList with `str` items. + """ + fips_restrictions: bool | None + """Use FIPS compliant algorithms.""" + hostkey: Hostkey + """Subclass of AvdModel.""" + enable: bool | None + """Enable SSH daemon.""" + connection: Connection + """Subclass of AvdModel.""" + vrfs: Vrfs + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + log_level: str | None + """SSH daemon log level.""" + client_alive: ClientAlive + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + authentication: Authentication | UndefinedType = Undefined, + access_groups: AccessGroups | UndefinedType = Undefined, + ipv6_access_groups: Ipv6AccessGroups | UndefinedType = Undefined, + idle_timeout: int | None | UndefinedType = Undefined, + cipher: Cipher | UndefinedType = Undefined, + key_exchange: KeyExchange | UndefinedType = Undefined, + mac: Mac | UndefinedType = Undefined, + fips_restrictions: bool | None | UndefinedType = Undefined, + hostkey: Hostkey | UndefinedType = Undefined, + enable: bool | None | UndefinedType = Undefined, + connection: Connection | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + log_level: str | None | UndefinedType = Undefined, + client_alive: ClientAlive | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ManagementSsh. + + + Subclass of AvdModel. + + Args: + authentication: Subclass of AvdModel. + access_groups: Subclass of AvdList with `AccessGroupsItem` items. + ipv6_access_groups: Subclass of AvdList with `Ipv6AccessGroupsItem` items. + idle_timeout: Idle timeout in minutes. + cipher: + Cryptographic ciphers for SSH to use. + + Subclass of AvdList with `str` items. + key_exchange: + Cryptographic key exchange methods for SSH to use. + + Subclass of AvdList with `str` items. + mac: + Cryptographic MAC algorithms for SSH to use. + + Subclass of AvdList with `str` items. + fips_restrictions: Use FIPS compliant algorithms. + hostkey: Subclass of AvdModel. + enable: Enable SSH daemon. + connection: Subclass of AvdModel. + vrfs: Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`). + log_level: SSH daemon log level. + client_alive: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class ManagementTechSupport(AvdModel): + """Subclass of AvdModel.""" + + class PolicyShowTechSupport(AvdModel): + """Subclass of AvdModel.""" + + class ExcludeCommandsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"command": {"type": str}, "type": {"type": str, "default": "text"}, "_custom_data": {"type": dict}} + command: str | None + """Command to exclude from tech-support.""" + type: Literal["text", "json"] + """ + The supported values for type are platform dependent. + + Default value: `"text"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + command: str | None | UndefinedType = Undefined, + type: Literal["text", "json"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ExcludeCommandsItem. + + + Subclass of AvdModel. + + Args: + command: Command to exclude from tech-support. + type: The supported values for type are platform dependent. + _custom_data: _custom_data + + """ + + class ExcludeCommands(AvdList[ExcludeCommandsItem]): + """Subclass of AvdList with `ExcludeCommandsItem` items.""" + + ExcludeCommands._item_type = ExcludeCommandsItem + + class IncludeCommandsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"command": {"type": str}, "_custom_data": {"type": dict}} + command: str | None + """Command to include in tech-support.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, command: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + IncludeCommandsItem. + + + Subclass of AvdModel. + + Args: + command: Command to include in tech-support. + _custom_data: _custom_data + + """ + + class IncludeCommands(AvdList[IncludeCommandsItem]): + """Subclass of AvdList with `IncludeCommandsItem` items.""" + + IncludeCommands._item_type = IncludeCommandsItem + + _fields: ClassVar[dict] = { + "exclude_commands": {"type": ExcludeCommands}, + "include_commands": {"type": IncludeCommands}, + "_custom_data": {"type": dict}, + } + exclude_commands: ExcludeCommands + """Subclass of AvdList with `ExcludeCommandsItem` items.""" + include_commands: IncludeCommands + """Subclass of AvdList with `IncludeCommandsItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + exclude_commands: ExcludeCommands | UndefinedType = Undefined, + include_commands: IncludeCommands | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PolicyShowTechSupport. + + + Subclass of AvdModel. + + Args: + exclude_commands: Subclass of AvdList with `ExcludeCommandsItem` items. + include_commands: Subclass of AvdList with `IncludeCommandsItem` items. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"policy_show_tech_support": {"type": PolicyShowTechSupport}, "_custom_data": {"type": dict}} + policy_show_tech_support: PolicyShowTechSupport + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, policy_show_tech_support: PolicyShowTechSupport | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + ManagementTechSupport. + + + Subclass of AvdModel. + + Args: + policy_show_tech_support: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MatchListInput(AvdModel): + """Subclass of AvdModel.""" + + class PrefixIpv4Item(AvdModel): + """Subclass of AvdModel.""" + + class Prefixes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Prefixes._item_type = str + + _fields: ClassVar[dict] = {"name": {"type": str}, "prefixes": {"type": Prefixes}, "_custom_data": {"type": dict}} + name: str + """Prefix-List Name.""" + prefixes: Prefixes + """ + List of IPv4 prefixes (with the subnet mask e.g. 192.0.2.0/24). + + Subclass of AvdList with `str` + items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + prefixes: Prefixes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PrefixIpv4Item. + + + Subclass of AvdModel. + + Args: + name: Prefix-List Name. + prefixes: + List of IPv4 prefixes (with the subnet mask e.g. 192.0.2.0/24). + + Subclass of AvdList with `str` + items. + _custom_data: _custom_data + + """ + + class PrefixIpv4(AvdIndexedList[str, PrefixIpv4Item]): + """Subclass of AvdIndexedList with `PrefixIpv4Item` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PrefixIpv4._item_type = PrefixIpv4Item + + class PrefixIpv6Item(AvdModel): + """Subclass of AvdModel.""" + + class Prefixes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Prefixes._item_type = str + + _fields: ClassVar[dict] = {"name": {"type": str}, "prefixes": {"type": Prefixes}, "_custom_data": {"type": dict}} + name: str + """Prefix-List Name.""" + prefixes: Prefixes + """ + List of IPv6 prefixes (with the subnet mask e.g. 2001:db8:abcd:0013::/64). + + Subclass of AvdList with + `str` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + prefixes: Prefixes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PrefixIpv6Item. + + + Subclass of AvdModel. + + Args: + name: Prefix-List Name. + prefixes: + List of IPv6 prefixes (with the subnet mask e.g. 2001:db8:abcd:0013::/64). + + Subclass of AvdList with + `str` items. + _custom_data: _custom_data + + """ + + class PrefixIpv6(AvdIndexedList[str, PrefixIpv6Item]): + """Subclass of AvdIndexedList with `PrefixIpv6Item` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PrefixIpv6._item_type = PrefixIpv6Item + + class StringItem(AvdModel): + """Subclass of AvdModel.""" + + class SequenceNumbersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"sequence": {"type": int}, "match_regex": {"type": str}, "_custom_data": {"type": dict}} + sequence: int + """Sequence ID.""" + match_regex: str + """Regular Expression.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sequence: int | UndefinedType = Undefined, + match_regex: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceNumbersItem. + + + Subclass of AvdModel. + + Args: + sequence: Sequence ID. + match_regex: Regular Expression. + _custom_data: _custom_data + + """ + + class SequenceNumbers(AvdIndexedList[int, SequenceNumbersItem]): + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + + _primary_key: ClassVar[str] = "sequence" + + SequenceNumbers._item_type = SequenceNumbersItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "sequence_numbers": {"type": SequenceNumbers}, "_custom_data": {"type": dict}} + name: str + """Match-list Name.""" + sequence_numbers: SequenceNumbers + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + sequence_numbers: SequenceNumbers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StringItem. + + + Subclass of AvdModel. + + Args: + name: Match-list Name. + sequence_numbers: Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`). + _custom_data: _custom_data + + """ + + class String(AvdIndexedList[str, StringItem]): + """Subclass of AvdIndexedList with `StringItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + String._item_type = StringItem + + _fields: ClassVar[dict] = { + "prefix_ipv4": {"type": PrefixIpv4}, + "prefix_ipv6": {"type": PrefixIpv6}, + "string": {"type": String}, + "_custom_data": {"type": dict}, + } + prefix_ipv4: PrefixIpv4 + """Subclass of AvdIndexedList with `PrefixIpv4Item` items. Primary key is `name` (`str`).""" + prefix_ipv6: PrefixIpv6 + """Subclass of AvdIndexedList with `PrefixIpv6Item` items. Primary key is `name` (`str`).""" + string: String + """Subclass of AvdIndexedList with `StringItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix_ipv4: PrefixIpv4 | UndefinedType = Undefined, + prefix_ipv6: PrefixIpv6 | UndefinedType = Undefined, + string: String | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchListInput. + + + Subclass of AvdModel. + + Args: + prefix_ipv4: Subclass of AvdIndexedList with `PrefixIpv4Item` items. Primary key is `name` (`str`). + prefix_ipv6: Subclass of AvdIndexedList with `PrefixIpv6Item` items. Primary key is `name` (`str`). + string: Subclass of AvdIndexedList with `StringItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class McsClient(AvdModel): + """Subclass of AvdModel.""" + + class CvxSecondary(AvdModel): + """Subclass of AvdModel.""" + + class ServerHosts(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + ServerHosts._item_type = str + + _fields: ClassVar[dict] = {"name": {"type": str}, "shutdown": {"type": bool}, "server_hosts": {"type": ServerHosts}, "_custom_data": {"type": dict}} + name: str | None + shutdown: bool | None + server_hosts: ServerHosts + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + server_hosts: ServerHosts | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CvxSecondary. + + + Subclass of AvdModel. + + Args: + name: name + shutdown: shutdown + server_hosts: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"shutdown": {"type": bool}, "cvx_secondary": {"type": CvxSecondary}, "_custom_data": {"type": dict}} + shutdown: bool | None + cvx_secondary: CvxSecondary + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + shutdown: bool | None | UndefinedType = Undefined, + cvx_secondary: CvxSecondary | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + McsClient. + + + Subclass of AvdModel. + + Args: + shutdown: shutdown + cvx_secondary: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Metadata(AvdModel): + """Subclass of AvdModel.""" + + class CvTags(AvdModel): + """Subclass of AvdModel.""" + + class DeviceTagsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "value": {"type": str}, "_custom_data": {"type": dict}} + name: str + value: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + value: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DeviceTagsItem. + + + Subclass of AvdModel. + + Args: + name: name + value: value + _custom_data: _custom_data + + """ + + class DeviceTags(AvdList[DeviceTagsItem]): + """Subclass of AvdList with `DeviceTagsItem` items.""" + + DeviceTags._item_type = DeviceTagsItem + + class InterfaceTagsItem(AvdModel): + """Subclass of AvdModel.""" + + class TagsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "value": {"type": str}, "_custom_data": {"type": dict}} + name: str + value: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + value: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TagsItem. + + + Subclass of AvdModel. + + Args: + name: name + value: value + _custom_data: _custom_data + + """ + + class Tags(AvdList[TagsItem]): + """Subclass of AvdList with `TagsItem` items.""" + + Tags._item_type = TagsItem + + _fields: ClassVar[dict] = {"interface": {"type": str}, "tags": {"type": Tags}, "_custom_data": {"type": dict}} + interface: str + tags: Tags + """Subclass of AvdList with `TagsItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interface: str | UndefinedType = Undefined, + tags: Tags | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + InterfaceTagsItem. + + + Subclass of AvdModel. + + Args: + interface: interface + tags: Subclass of AvdList with `TagsItem` items. + _custom_data: _custom_data + + """ + + class InterfaceTags(AvdList[InterfaceTagsItem]): + """Subclass of AvdList with `InterfaceTagsItem` items.""" + + InterfaceTags._item_type = InterfaceTagsItem + + _fields: ClassVar[dict] = {"device_tags": {"type": DeviceTags}, "interface_tags": {"type": InterfaceTags}, "_custom_data": {"type": dict}} + device_tags: DeviceTags + """Subclass of AvdList with `DeviceTagsItem` items.""" + interface_tags: InterfaceTags + """Subclass of AvdList with `InterfaceTagsItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + device_tags: DeviceTags | UndefinedType = Undefined, + interface_tags: InterfaceTags | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CvTags. + + + Subclass of AvdModel. + + Args: + device_tags: Subclass of AvdList with `DeviceTagsItem` items. + interface_tags: Subclass of AvdList with `InterfaceTagsItem` items. + _custom_data: _custom_data + + """ + + class CvPathfinder(AvdModel): + """Subclass of AvdModel.""" + + class PathfindersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"vtep_ip": {"type": str}, "_custom_data": {"type": dict}} + vtep_ip: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, vtep_ip: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + PathfindersItem. + + + Subclass of AvdModel. + + Args: + vtep_ip: vtep_ip + _custom_data: _custom_data + + """ + + class Pathfinders(AvdList[PathfindersItem]): + """Subclass of AvdList with `PathfindersItem` items.""" + + Pathfinders._item_type = PathfindersItem + + class InterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "carrier": {"type": str}, + "circuit_id": {"type": str}, + "pathgroup": {"type": str}, + "public_ip": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str | None + carrier: str | None + circuit_id: str | None + pathgroup: str | None + public_ip: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + carrier: str | None | UndefinedType = Undefined, + circuit_id: str | None | UndefinedType = Undefined, + pathgroup: str | None | UndefinedType = Undefined, + public_ip: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + InterfacesItem. + + + Subclass of AvdModel. + + Args: + name: name + carrier: carrier + circuit_id: circuit_id + pathgroup: pathgroup + public_ip: public_ip + _custom_data: _custom_data + + """ + + class Interfaces(AvdList[InterfacesItem]): + """Subclass of AvdList with `InterfacesItem` items.""" + + Interfaces._item_type = InterfacesItem + + class PathgroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class CarriersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, name: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + CarriersItem. + + + Subclass of AvdModel. + + Args: + name: name + _custom_data: _custom_data + + """ + + class Carriers(AvdList[CarriersItem]): + """Subclass of AvdList with `CarriersItem` items.""" + + Carriers._item_type = CarriersItem + + class ImportedCarriersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, name: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + ImportedCarriersItem. + + + Subclass of AvdModel. + + Args: + name: name + _custom_data: _custom_data + + """ + + class ImportedCarriers(AvdList[ImportedCarriersItem]): + """Subclass of AvdList with `ImportedCarriersItem` items.""" + + ImportedCarriers._item_type = ImportedCarriersItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "carriers": {"type": Carriers}, + "imported_carriers": {"type": ImportedCarriers}, + "_custom_data": {"type": dict}, + } + name: str + carriers: Carriers + """Subclass of AvdList with `CarriersItem` items.""" + imported_carriers: ImportedCarriers + """Subclass of AvdList with `ImportedCarriersItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + carriers: Carriers | UndefinedType = Undefined, + imported_carriers: ImportedCarriers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PathgroupsItem. + + + Subclass of AvdModel. + + Args: + name: name + carriers: Subclass of AvdList with `CarriersItem` items. + imported_carriers: Subclass of AvdList with `ImportedCarriersItem` items. + _custom_data: _custom_data + + """ + + class Pathgroups(AvdList[PathgroupsItem]): + """Subclass of AvdList with `PathgroupsItem` items.""" + + Pathgroups._item_type = PathgroupsItem + + class RegionsItem(AvdModel): + """Subclass of AvdModel.""" + + class ZonesItem(AvdModel): + """Subclass of AvdModel.""" + + class SitesItem(AvdModel): + """Subclass of AvdModel.""" + + class Location(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"address": {"type": str}, "_custom_data": {"type": dict}} + address: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, address: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Location. + + + Subclass of AvdModel. + + Args: + address: address + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"id": {"type": int}, "name": {"type": str}, "location": {"type": Location}, "_custom_data": {"type": dict}} + id: int | None + name: str | None + location: Location + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + location: Location | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SitesItem. + + + Subclass of AvdModel. + + Args: + id: id + name: name + location: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Sites(AvdList[SitesItem]): + """Subclass of AvdList with `SitesItem` items.""" + + Sites._item_type = SitesItem + + _fields: ClassVar[dict] = {"id": {"type": int}, "name": {"type": str}, "sites": {"type": Sites}, "_custom_data": {"type": dict}} + id: int | None + name: str | None + sites: Sites + """Subclass of AvdList with `SitesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + sites: Sites | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ZonesItem. + + + Subclass of AvdModel. + + Args: + id: id + name: name + sites: Subclass of AvdList with `SitesItem` items. + _custom_data: _custom_data + + """ + + class Zones(AvdList[ZonesItem]): + """Subclass of AvdList with `ZonesItem` items.""" + + Zones._item_type = ZonesItem + + _fields: ClassVar[dict] = {"id": {"type": int}, "name": {"type": str}, "zones": {"type": Zones}, "_custom_data": {"type": dict}} + id: int | None + name: str | None + zones: Zones + """Subclass of AvdList with `ZonesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + zones: Zones | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RegionsItem. + + + Subclass of AvdModel. + + Args: + id: id + name: name + zones: Subclass of AvdList with `ZonesItem` items. + _custom_data: _custom_data + + """ + + class Regions(AvdList[RegionsItem]): + """Subclass of AvdList with `RegionsItem` items.""" + + Regions._item_type = RegionsItem + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + class AvtsItem(AvdModel): + """Subclass of AvdModel.""" + + class Constraints(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "jitter": {"type": int}, + "latency": {"type": int}, + "lossrate": {"type": str}, + "hop_count": {"type": str}, + "_custom_data": {"type": dict}, + } + jitter: int | None + latency: int | None + lossrate: str | None + hop_count: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + jitter: int | None | UndefinedType = Undefined, + latency: int | None | UndefinedType = Undefined, + lossrate: str | None | UndefinedType = Undefined, + hop_count: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Constraints. + + + Subclass of AvdModel. + + Args: + jitter: jitter + latency: latency + lossrate: lossrate + hop_count: hop_count + _custom_data: _custom_data + + """ + + class PathgroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "preference": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + preference: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + preference: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PathgroupsItem. + + + Subclass of AvdModel. + + Args: + name: name + preference: preference + _custom_data: _custom_data + + """ + + class Pathgroups(AvdList[PathgroupsItem]): + """Subclass of AvdList with `PathgroupsItem` items.""" + + Pathgroups._item_type = PathgroupsItem + + class ApplicationProfiles(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + ApplicationProfiles._item_type = str + + _fields: ClassVar[dict] = { + "constraints": {"type": Constraints}, + "description": {"type": str}, + "id": {"type": int}, + "name": {"type": str}, + "pathgroups": {"type": Pathgroups}, + "application_profiles": {"type": ApplicationProfiles}, + "_custom_data": {"type": dict}, + } + constraints: Constraints + """Subclass of AvdModel.""" + description: str | None + id: int | None + name: str | None + pathgroups: Pathgroups + """Subclass of AvdList with `PathgroupsItem` items.""" + application_profiles: ApplicationProfiles + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + constraints: Constraints | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + id: int | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + pathgroups: Pathgroups | UndefinedType = Undefined, + application_profiles: ApplicationProfiles | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AvtsItem. + + + Subclass of AvdModel. + + Args: + constraints: Subclass of AvdModel. + description: description + id: id + name: name + pathgroups: Subclass of AvdList with `PathgroupsItem` items. + application_profiles: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class Avts(AvdList[AvtsItem]): + """Subclass of AvdList with `AvtsItem` items.""" + + Avts._item_type = AvtsItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "vni": {"type": int}, "avts": {"type": Avts}, "_custom_data": {"type": dict}} + name: str | None + vni: int | None + avts: Avts + """Subclass of AvdList with `AvtsItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + vni: int | None | UndefinedType = Undefined, + avts: Avts | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: name + vni: vni + avts: Subclass of AvdList with `AvtsItem` items. + _custom_data: _custom_data + + """ + + class Vrfs(AvdList[VrfsItem]): + """Subclass of AvdList with `VrfsItem` items.""" + + Vrfs._item_type = VrfsItem + + class InternetExitPoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + class VpnCredentialsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "fqdn": {"type": str}, + "vpn_type": {"type": str}, + "pre_shared_key": {"type": str}, + "_custom_data": {"type": dict}, + } + fqdn: str + vpn_type: str + pre_shared_key: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + fqdn: str | UndefinedType = Undefined, + vpn_type: str | UndefinedType = Undefined, + pre_shared_key: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VpnCredentialsItem. + + + Subclass of AvdModel. + + Args: + fqdn: fqdn + vpn_type: vpn_type + pre_shared_key: pre_shared_key + _custom_data: _custom_data + + """ + + class VpnCredentials(AvdList[VpnCredentialsItem]): + """Subclass of AvdList with `VpnCredentialsItem` items.""" + + VpnCredentials._item_type = VpnCredentialsItem + + class TunnelsItem(AvdModel): + """Subclass of AvdModel.""" + + class Endpoint(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "datacenter": {"type": str}, + "city": {"type": str}, + "country": {"type": str}, + "region": {"type": str}, + "latitude": {"type": str}, + "longitude": {"type": str}, + "_custom_data": {"type": dict}, + } + ip_address: str + datacenter: str + city: str + country: str + region: str + latitude: str + longitude: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + datacenter: str | UndefinedType = Undefined, + city: str | UndefinedType = Undefined, + country: str | UndefinedType = Undefined, + region: str | UndefinedType = Undefined, + latitude: str | UndefinedType = Undefined, + longitude: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Endpoint. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + datacenter: datacenter + city: city + country: country + region: region + latitude: latitude + longitude: longitude + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "preference": {"type": str}, + "endpoint": {"type": Endpoint}, + "_custom_data": {"type": dict}, + } + name: str + preference: str + endpoint: Endpoint + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + preference: str | UndefinedType = Undefined, + endpoint: Endpoint | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TunnelsItem. + + + Subclass of AvdModel. + + Args: + name: name + preference: preference + endpoint: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Tunnels(AvdList[TunnelsItem]): + """Subclass of AvdList with `TunnelsItem` items.""" + + Tunnels._item_type = TunnelsItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "type": {"type": str}, + "city": {"type": str}, + "country": {"type": str}, + "upload_bandwidth": {"type": int}, + "download_bandwidth": {"type": int}, + "firewall": {"type": bool}, + "ips_control": {"type": bool}, + "acceptable_use_policy": {"type": bool}, + "vpn_credentials": {"type": VpnCredentials}, + "tunnels": {"type": Tunnels}, + "_custom_data": {"type": dict}, + } + name: str + type: str + city: str + country: str + upload_bandwidth: int | None + download_bandwidth: int | None + firewall: bool + ips_control: bool + acceptable_use_policy: bool + vpn_credentials: VpnCredentials + """Subclass of AvdList with `VpnCredentialsItem` items.""" + tunnels: Tunnels + """Subclass of AvdList with `TunnelsItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + type: str | UndefinedType = Undefined, + city: str | UndefinedType = Undefined, + country: str | UndefinedType = Undefined, + upload_bandwidth: int | None | UndefinedType = Undefined, + download_bandwidth: int | None | UndefinedType = Undefined, + firewall: bool | UndefinedType = Undefined, + ips_control: bool | UndefinedType = Undefined, + acceptable_use_policy: bool | UndefinedType = Undefined, + vpn_credentials: VpnCredentials | UndefinedType = Undefined, + tunnels: Tunnels | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + InternetExitPoliciesItem. + + + Subclass of AvdModel. + + Args: + name: name + type: type + city: city + country: country + upload_bandwidth: upload_bandwidth + download_bandwidth: download_bandwidth + firewall: firewall + ips_control: ips_control + acceptable_use_policy: acceptable_use_policy + vpn_credentials: Subclass of AvdList with `VpnCredentialsItem` items. + tunnels: Subclass of AvdList with `TunnelsItem` items. + _custom_data: _custom_data + + """ + + class InternetExitPolicies(AvdList[InternetExitPoliciesItem]): + """Subclass of AvdList with `InternetExitPoliciesItem` items.""" + + InternetExitPolicies._item_type = InternetExitPoliciesItem + + class Applications(AvdModel): + """Subclass of AvdModel.""" + + class ProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class BuiltinApplicationsItem(AvdModel): + """Subclass of AvdModel.""" + + class Services(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Services._item_type = str + + _fields: ClassVar[dict] = {"name": {"type": str}, "services": {"type": Services}, "_custom_data": {"type": dict}} + name: str | None + services: Services + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + services: Services | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BuiltinApplicationsItem. + + + Subclass of AvdModel. + + Args: + name: name + services: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class BuiltinApplications(AvdList[BuiltinApplicationsItem]): + """Subclass of AvdList with `BuiltinApplicationsItem` items.""" + + BuiltinApplications._item_type = BuiltinApplicationsItem + + class UserDefinedApplicationsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, name: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + UserDefinedApplicationsItem. + + + Subclass of AvdModel. + + Args: + name: name + _custom_data: _custom_data + + """ + + class UserDefinedApplications(AvdList[UserDefinedApplicationsItem]): + """Subclass of AvdList with `UserDefinedApplicationsItem` items.""" + + UserDefinedApplications._item_type = UserDefinedApplicationsItem + + class CategoriesItem(AvdModel): + """Subclass of AvdModel.""" + + class Services(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Services._item_type = str + + _fields: ClassVar[dict] = {"category": {"type": str}, "services": {"type": Services}, "_custom_data": {"type": dict}} + category: str | None + services: Services + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + category: str | None | UndefinedType = Undefined, + services: Services | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CategoriesItem. + + + Subclass of AvdModel. + + Args: + category: category + services: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class Categories(AvdList[CategoriesItem]): + """Subclass of AvdList with `CategoriesItem` items.""" + + Categories._item_type = CategoriesItem + + class TransportProtocols(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + TransportProtocols._item_type = str + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "builtin_applications": {"type": BuiltinApplications}, + "user_defined_applications": {"type": UserDefinedApplications}, + "categories": {"type": Categories}, + "transport_protocols": {"type": TransportProtocols}, + "_custom_data": {"type": dict}, + } + name: str | None + builtin_applications: BuiltinApplications + """Subclass of AvdList with `BuiltinApplicationsItem` items.""" + user_defined_applications: UserDefinedApplications + """Subclass of AvdList with `UserDefinedApplicationsItem` items.""" + categories: Categories + """Subclass of AvdList with `CategoriesItem` items.""" + transport_protocols: TransportProtocols + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + builtin_applications: BuiltinApplications | UndefinedType = Undefined, + user_defined_applications: UserDefinedApplications | UndefinedType = Undefined, + categories: Categories | UndefinedType = Undefined, + transport_protocols: TransportProtocols | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ProfilesItem. + + + Subclass of AvdModel. + + Args: + name: name + builtin_applications: Subclass of AvdList with `BuiltinApplicationsItem` items. + user_defined_applications: Subclass of AvdList with `UserDefinedApplicationsItem` items. + categories: Subclass of AvdList with `CategoriesItem` items. + transport_protocols: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class Profiles(AvdList[ProfilesItem]): + """Subclass of AvdList with `ProfilesItem` items.""" + + Profiles._item_type = ProfilesItem + + class Categories(AvdModel): + """Subclass of AvdModel.""" + + class BuiltinApplicationsItem(AvdModel): + """Subclass of AvdModel.""" + + class Services(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Services._item_type = str + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "category": {"type": str}, + "services": {"type": Services}, + "_custom_data": {"type": dict}, + } + name: str | None + category: str | None + services: Services + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + category: str | None | UndefinedType = Undefined, + services: Services | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BuiltinApplicationsItem. + + + Subclass of AvdModel. + + Args: + name: name + category: category + services: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class BuiltinApplications(AvdList[BuiltinApplicationsItem]): + """Subclass of AvdList with `BuiltinApplicationsItem` items.""" + + BuiltinApplications._item_type = BuiltinApplicationsItem + + class UserDefinedApplicationsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "category": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + category: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + category: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + UserDefinedApplicationsItem. + + + Subclass of AvdModel. + + Args: + name: name + category: category + _custom_data: _custom_data + + """ + + class UserDefinedApplications(AvdList[UserDefinedApplicationsItem]): + """Subclass of AvdList with `UserDefinedApplicationsItem` items.""" + + UserDefinedApplications._item_type = UserDefinedApplicationsItem + + _fields: ClassVar[dict] = { + "builtin_applications": {"type": BuiltinApplications}, + "user_defined_applications": {"type": UserDefinedApplications}, + "_custom_data": {"type": dict}, + } + builtin_applications: BuiltinApplications + """Subclass of AvdList with `BuiltinApplicationsItem` items.""" + user_defined_applications: UserDefinedApplications + """Subclass of AvdList with `UserDefinedApplicationsItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + builtin_applications: BuiltinApplications | UndefinedType = Undefined, + user_defined_applications: UserDefinedApplications | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Categories. + + + Subclass of AvdModel. + + Args: + builtin_applications: Subclass of AvdList with `BuiltinApplicationsItem` items. + user_defined_applications: Subclass of AvdList with `UserDefinedApplicationsItem` items. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"profiles": {"type": Profiles}, "categories": {"type": Categories}, "_custom_data": {"type": dict}} + profiles: Profiles + """Subclass of AvdList with `ProfilesItem` items.""" + categories: Categories + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profiles: Profiles | UndefinedType = Undefined, + categories: Categories | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Applications. + + + Subclass of AvdModel. + + Args: + profiles: Subclass of AvdList with `ProfilesItem` items. + categories: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "role": {"type": str}, + "region": {"type": str}, + "zone": {"type": str}, + "site": {"type": str}, + "vtep_ip": {"type": str}, + "ssl_profile": {"type": str}, + "address": {"type": str}, + "pathfinders": {"type": Pathfinders}, + "interfaces": {"type": Interfaces}, + "pathgroups": {"type": Pathgroups}, + "regions": {"type": Regions}, + "vrfs": {"type": Vrfs}, + "internet_exit_policies": {"type": InternetExitPolicies}, + "applications": {"type": Applications}, + "_custom_data": {"type": dict}, + } + role: str | None + region: str | None + zone: str | None + site: str | None + vtep_ip: str | None + ssl_profile: str | None + address: str | None + pathfinders: Pathfinders + """Subclass of AvdList with `PathfindersItem` items.""" + interfaces: Interfaces + """Subclass of AvdList with `InterfacesItem` items.""" + pathgroups: Pathgroups + """Subclass of AvdList with `PathgroupsItem` items.""" + regions: Regions + """Subclass of AvdList with `RegionsItem` items.""" + vrfs: Vrfs + """Subclass of AvdList with `VrfsItem` items.""" + internet_exit_policies: InternetExitPolicies + """Subclass of AvdList with `InternetExitPoliciesItem` items.""" + applications: Applications + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + role: str | None | UndefinedType = Undefined, + region: str | None | UndefinedType = Undefined, + zone: str | None | UndefinedType = Undefined, + site: str | None | UndefinedType = Undefined, + vtep_ip: str | None | UndefinedType = Undefined, + ssl_profile: str | None | UndefinedType = Undefined, + address: str | None | UndefinedType = Undefined, + pathfinders: Pathfinders | UndefinedType = Undefined, + interfaces: Interfaces | UndefinedType = Undefined, + pathgroups: Pathgroups | UndefinedType = Undefined, + regions: Regions | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + internet_exit_policies: InternetExitPolicies | UndefinedType = Undefined, + applications: Applications | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CvPathfinder. + + + Subclass of AvdModel. + + Args: + role: role + region: region + zone: zone + site: site + vtep_ip: vtep_ip + ssl_profile: ssl_profile + address: address + pathfinders: Subclass of AvdList with `PathfindersItem` items. + interfaces: Subclass of AvdList with `InterfacesItem` items. + pathgroups: Subclass of AvdList with `PathgroupsItem` items. + regions: Subclass of AvdList with `RegionsItem` items. + vrfs: Subclass of AvdList with `VrfsItem` items. + internet_exit_policies: Subclass of AvdList with `InternetExitPoliciesItem` items. + applications: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "platform": {"type": str}, + "system_mac_address": {"type": str}, + "cv_tags": {"type": CvTags}, + "cv_pathfinder": {"type": CvPathfinder}, + "_custom_data": {"type": dict}, + } + platform: str | None + system_mac_address: str | None + cv_tags: CvTags + """Subclass of AvdModel.""" + cv_pathfinder: CvPathfinder + """ + Metadata used for CV Pathfinder visualization on CloudVision. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + platform: str | None | UndefinedType = Undefined, + system_mac_address: str | None | UndefinedType = Undefined, + cv_tags: CvTags | UndefinedType = Undefined, + cv_pathfinder: CvPathfinder | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Metadata. + + + Subclass of AvdModel. + + Args: + platform: platform + system_mac_address: system_mac_address + cv_tags: Subclass of AvdModel. + cv_pathfinder: + Metadata used for CV Pathfinder visualization on CloudVision. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MlagConfiguration(AvdModel): + """Subclass of AvdModel.""" + + class PeerAddressHeartbeat(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"peer_ip": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + peer_ip: str | None + """IPv4 or IPv6 Address.""" + vrf: str | None + """VRF Name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + peer_ip: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeerAddressHeartbeat. + + + Subclass of AvdModel. + + Args: + peer_ip: IPv4 or IPv6 Address. + vrf: VRF Name. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "domain_id": {"type": str}, + "heartbeat_interval": {"type": int}, + "local_interface": {"type": str}, + "peer_address": {"type": str}, + "peer_address_heartbeat": {"type": PeerAddressHeartbeat}, + "dual_primary_detection_delay": {"type": int}, + "dual_primary_recovery_delay_mlag": {"type": int}, + "dual_primary_recovery_delay_non_mlag": {"type": int}, + "peer_link": {"type": str}, + "reload_delay_mlag": {"type": str}, + "reload_delay_non_mlag": {"type": str}, + "_custom_data": {"type": dict}, + } + domain_id: str | None + heartbeat_interval: int | None + """Heartbeat interval in milliseconds.""" + local_interface: str | None + """Local Interface Name.""" + peer_address: str | None + """IPv4 or IPv6 Address.""" + peer_address_heartbeat: PeerAddressHeartbeat + """Subclass of AvdModel.""" + dual_primary_detection_delay: int | None + """Delay in seconds.""" + dual_primary_recovery_delay_mlag: int | None + """Delay in seconds.""" + dual_primary_recovery_delay_non_mlag: int | None + """Delay in seconds.""" + peer_link: str | None + """Port-Channel interface name.""" + reload_delay_mlag: str | None + """Delay in seconds <0-86400> or 'infinity'.""" + reload_delay_non_mlag: str | None + """Delay in seconds <0-86400> or 'infinity'.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + domain_id: str | None | UndefinedType = Undefined, + heartbeat_interval: int | None | UndefinedType = Undefined, + local_interface: str | None | UndefinedType = Undefined, + peer_address: str | None | UndefinedType = Undefined, + peer_address_heartbeat: PeerAddressHeartbeat | UndefinedType = Undefined, + dual_primary_detection_delay: int | None | UndefinedType = Undefined, + dual_primary_recovery_delay_mlag: int | None | UndefinedType = Undefined, + dual_primary_recovery_delay_non_mlag: int | None | UndefinedType = Undefined, + peer_link: str | None | UndefinedType = Undefined, + reload_delay_mlag: str | None | UndefinedType = Undefined, + reload_delay_non_mlag: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MlagConfiguration. + + + Subclass of AvdModel. + + Args: + domain_id: domain_id + heartbeat_interval: Heartbeat interval in milliseconds. + local_interface: Local Interface Name. + peer_address: IPv4 or IPv6 Address. + peer_address_heartbeat: Subclass of AvdModel. + dual_primary_detection_delay: Delay in seconds. + dual_primary_recovery_delay_mlag: Delay in seconds. + dual_primary_recovery_delay_non_mlag: Delay in seconds. + peer_link: Port-Channel interface name. + reload_delay_mlag: Delay in seconds <0-86400> or 'infinity'. + reload_delay_non_mlag: Delay in seconds <0-86400> or 'infinity'. + _custom_data: _custom_data + + """ + + class MonitorConnectivity(AvdModel): + """Subclass of AvdModel.""" + + class InterfaceSetsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "interfaces": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + interfaces: str | None + """ + Interface range(s) should be of same type, Ethernet, Loopback, Management etc. + Multiple interface + ranges can be specified separated by ",". + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + interfaces: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + InterfaceSetsItem. + + + Subclass of AvdModel. + + Args: + name: name + interfaces: + Interface range(s) should be of same type, Ethernet, Loopback, Management etc. + Multiple interface + ranges can be specified separated by ",". + _custom_data: _custom_data + + """ + + class InterfaceSets(AvdList[InterfaceSetsItem]): + """Subclass of AvdList with `InterfaceSetsItem` items.""" + + InterfaceSets._item_type = InterfaceSetsItem + + class HostsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "description": {"type": str}, + "ip": {"type": str}, + "local_interfaces": {"type": str}, + "address_only": {"type": bool, "default": True}, + "url": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Host Name.""" + description: str | None + ip: str | None + local_interfaces: str | None + address_only: bool + """ + When address-only is configured, the source IP of the packet is set to the interface + IP but the + packet may exit the device via a different interface. + When set to `false`, the probe uses the + interface to exit the device. + + Default value: `True` + """ + url: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + ip: str | None | UndefinedType = Undefined, + local_interfaces: str | None | UndefinedType = Undefined, + address_only: bool | UndefinedType = Undefined, + url: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + HostsItem. + + + Subclass of AvdModel. + + Args: + name: Host Name. + description: description + ip: ip + local_interfaces: local_interfaces + address_only: + When address-only is configured, the source IP of the packet is set to the interface + IP but the + packet may exit the device via a different interface. + When set to `false`, the probe uses the + interface to exit the device. + url: url + _custom_data: _custom_data + + """ + + class Hosts(AvdIndexedList[str, HostsItem]): + """Subclass of AvdIndexedList with `HostsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Hosts._item_type = HostsItem + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + class InterfaceSetsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "interfaces": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + interfaces: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + interfaces: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + InterfaceSetsItem. + + + Subclass of AvdModel. + + Args: + name: name + interfaces: interfaces + _custom_data: _custom_data + + """ + + class InterfaceSets(AvdList[InterfaceSetsItem]): + """Subclass of AvdList with `InterfaceSetsItem` items.""" + + InterfaceSets._item_type = InterfaceSetsItem + + class HostsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "description": {"type": str}, + "ip": {"type": str}, + "local_interfaces": {"type": str}, + "address_only": {"type": bool, "default": True}, + "url": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Host name.""" + description: str | None + ip: str | None + local_interfaces: str | None + address_only: bool + """ + When address-only is configured, the source IP of the packet is set to the interface + IP but the + packet may exit the device via a different interface. + When set to `false`, the probe uses the + interface to exit the device. + + Default value: `True` + """ + url: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + ip: str | None | UndefinedType = Undefined, + local_interfaces: str | None | UndefinedType = Undefined, + address_only: bool | UndefinedType = Undefined, + url: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + HostsItem. + + + Subclass of AvdModel. + + Args: + name: Host name. + description: description + ip: ip + local_interfaces: local_interfaces + address_only: + When address-only is configured, the source IP of the packet is set to the interface + IP but the + packet may exit the device via a different interface. + When set to `false`, the probe uses the + interface to exit the device. + url: url + _custom_data: _custom_data + + """ + + class Hosts(AvdIndexedList[str, HostsItem]): + """Subclass of AvdIndexedList with `HostsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Hosts._item_type = HostsItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "description": {"type": str}, + "interface_sets": {"type": InterfaceSets}, + "local_interfaces": {"type": str}, + "address_only": {"type": bool, "default": True}, + "hosts": {"type": Hosts}, + "_custom_data": {"type": dict}, + } + name: str + """VRF Name.""" + description: str | None + interface_sets: InterfaceSets + """Subclass of AvdList with `InterfaceSetsItem` items.""" + local_interfaces: str | None + address_only: bool + """ + When address-only is configured, the source IP of the packet is set to the interface + IP but the + packet may exit the device via a different interface. + When set to `false`, the probe uses the + interface to exit the device. + + Default value: `True` + """ + hosts: Hosts + """Subclass of AvdIndexedList with `HostsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + interface_sets: InterfaceSets | UndefinedType = Undefined, + local_interfaces: str | None | UndefinedType = Undefined, + address_only: bool | UndefinedType = Undefined, + hosts: Hosts | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: VRF Name. + description: description + interface_sets: Subclass of AvdList with `InterfaceSetsItem` items. + local_interfaces: local_interfaces + address_only: + When address-only is configured, the source IP of the packet is set to the interface + IP but the + packet may exit the device via a different interface. + When set to `false`, the probe uses the + interface to exit the device. + hosts: Subclass of AvdIndexedList with `HostsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + _fields: ClassVar[dict] = { + "shutdown": {"type": bool}, + "interval": {"type": int}, + "interface_sets": {"type": InterfaceSets}, + "local_interfaces": {"type": str}, + "address_only": {"type": bool, "default": True}, + "hosts": {"type": Hosts}, + "vrfs": {"type": Vrfs}, + "_custom_data": {"type": dict}, + } + shutdown: bool | None + interval: int | None + interface_sets: InterfaceSets + """Subclass of AvdList with `InterfaceSetsItem` items.""" + local_interfaces: str | None + address_only: bool + """ + When address-only is configured, the source IP of the packet is set to the interface + IP but the + packet may exit the device via a different interface. + When set to `false`, the probe uses the + interface to exit the device. + + Default value: `True` + """ + hosts: Hosts + """Subclass of AvdIndexedList with `HostsItem` items. Primary key is `name` (`str`).""" + vrfs: Vrfs + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + shutdown: bool | None | UndefinedType = Undefined, + interval: int | None | UndefinedType = Undefined, + interface_sets: InterfaceSets | UndefinedType = Undefined, + local_interfaces: str | None | UndefinedType = Undefined, + address_only: bool | UndefinedType = Undefined, + hosts: Hosts | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MonitorConnectivity. + + + Subclass of AvdModel. + + Args: + shutdown: shutdown + interval: interval + interface_sets: Subclass of AvdList with `InterfaceSetsItem` items. + local_interfaces: local_interfaces + address_only: + When address-only is configured, the source IP of the packet is set to the interface + IP but the + packet may exit the device via a different interface. + When set to `false`, the probe uses the + interface to exit the device. + hosts: Subclass of AvdIndexedList with `HostsItem` items. Primary key is `name` (`str`). + vrfs: Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class MonitorLayer1(AvdModel): + """Subclass of AvdModel.""" + + class LoggingTransceiver(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"dom": {"type": bool}, "communication": {"type": bool}, "enabled": {"type": bool}, "_custom_data": {"type": dict}} + dom: bool | None + """Enable transceiver Digital Optical Monitoring (DOM) logging.""" + communication: bool | None + """Enable transceiver SMBus fail and reset logging.""" + enabled: bool | None + """ + Some platforms support only the `logging transceiver` command. `enabled` key configures this + command. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dom: bool | None | UndefinedType = Undefined, + communication: bool | None | UndefinedType = Undefined, + enabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LoggingTransceiver. + + + Subclass of AvdModel. + + Args: + dom: Enable transceiver Digital Optical Monitoring (DOM) logging. + communication: Enable transceiver SMBus fail and reset logging. + enabled: + Some platforms support only the `logging transceiver` command. `enabled` key configures this + command. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "logging_mac_fault": {"type": bool}, + "logging_transceiver": {"type": LoggingTransceiver}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Enable monitor layer1.""" + logging_mac_fault: bool | None + """Enable MAC fault logging.""" + logging_transceiver: LoggingTransceiver + """ + Configure transceiver monitoring logging. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + logging_mac_fault: bool | None | UndefinedType = Undefined, + logging_transceiver: LoggingTransceiver | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MonitorLayer1. + + + Subclass of AvdModel. + + Args: + enabled: Enable monitor layer1. + logging_mac_fault: Enable MAC fault logging. + logging_transceiver: + Configure transceiver monitoring logging. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MonitorServerRadius(AvdModel): + """Subclass of AvdModel.""" + + class Probe(AvdModel): + """Subclass of AvdModel.""" + + class AccessRequest(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "username": {"type": str}, + "password": {"type": str}, + "password_type": {"type": str, "default": "7"}, + "_custom_data": {"type": dict}, + } + username: str | None + password: str | None + """Encrypted password using the `password_type`.""" + password_type: Literal["0", "7", "8a"] + """Default value: `"7"`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + username: str | None | UndefinedType = Undefined, + password: str | None | UndefinedType = Undefined, + password_type: Literal["0", "7", "8a"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AccessRequest. + + + Subclass of AvdModel. + + Args: + username: username + password: Encrypted password using the `password_type`. + password_type: password_type + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "interval": {"type": int}, + "threshold_failure": {"type": int}, + "method": {"type": str}, + "access_request": {"type": AccessRequest}, + "_custom_data": {"type": dict}, + } + interval: int | None + """Server probe interval in seconds.""" + threshold_failure: int | None + """Number of consecutive failed probes before a server is marked as dead.""" + method: Literal["status-server", "access-request"] | None + """Method used to probe the server. `status-server` is the EOS default method.""" + access_request: AccessRequest + """ + This can only be set when `method` is `access_request`. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | None | UndefinedType = Undefined, + threshold_failure: int | None | UndefinedType = Undefined, + method: Literal["status-server", "access-request"] | None | UndefinedType = Undefined, + access_request: AccessRequest | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Probe. + + + Subclass of AvdModel. + + Args: + interval: Server probe interval in seconds. + threshold_failure: Number of consecutive failed probes before a server is marked as dead. + method: Method used to probe the server. `status-server` is the EOS default method. + access_request: + This can only be set when `method` is `access_request`. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"service_dot1x": {"type": bool}, "probe": {"type": Probe}, "_custom_data": {"type": dict}} + service_dot1x: bool | None + """Monitor servers used for 802.1X authentication.""" + probe: Probe + """ + Settings for probe sent to the server. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + service_dot1x: bool | None | UndefinedType = Undefined, + probe: Probe | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MonitorServerRadius. + + + Subclass of AvdModel. + + Args: + service_dot1x: Monitor servers used for 802.1X authentication. + probe: + Settings for probe sent to the server. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MonitorSessionDefaultEncapsulationGre(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"payload": {"type": str}, "_custom_data": {"type": dict}} + payload: Literal["full-packet", "inner-packet"] | None + """Mirroring GRE payload type configuration commands.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + payload: Literal["full-packet", "inner-packet"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MonitorSessionDefaultEncapsulationGre. + + + Subclass of AvdModel. + + Args: + payload: Mirroring GRE payload type configuration commands. + _custom_data: _custom_data + + """ + + class MonitorSessionsItem(AvdModel): + """Subclass of AvdModel.""" + + class SourcesItem(AvdModel): + """Subclass of AvdModel.""" + + class AccessGroup(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"type": {"type": str}, "name": {"type": str}, "priority": {"type": int}, "_custom_data": {"type": dict}} + type: Literal["ip", "ipv6", "mac"] | None + name: str | None + """ACL Name.""" + priority: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + type: Literal["ip", "ipv6", "mac"] | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AccessGroup. + + + Subclass of AvdModel. + + Args: + type: type + name: ACL Name. + priority: priority + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"name": {"type": str}, "direction": {"type": str}, "access_group": {"type": AccessGroup}, "_custom_data": {"type": dict}} + name: str | None + """Interface name, range or comma separated list.""" + direction: Literal["rx", "tx", "both"] | None + access_group: AccessGroup + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + direction: Literal["rx", "tx", "both"] | None | UndefinedType = Undefined, + access_group: AccessGroup | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SourcesItem. + + + Subclass of AvdModel. + + Args: + name: Interface name, range or comma separated list. + direction: direction + access_group: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Sources(AvdList[SourcesItem]): + """Subclass of AvdList with `SourcesItem` items.""" + + Sources._item_type = SourcesItem + + class Destinations(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Destinations._item_type = str + + class AccessGroup(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"type": {"type": str}, "name": {"type": str}, "_custom_data": {"type": dict}} + type: Literal["ip", "ipv6", "mac"] | None + name: str | None + """ACL Name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + type: Literal["ip", "ipv6", "mac"] | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AccessGroup. + + + Subclass of AvdModel. + + Args: + type: type + name: ACL Name. + _custom_data: _custom_data + + """ + + class Truncate(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "size": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool | None + size: int | None + """Size in bytes.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + size: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Truncate. + + + Subclass of AvdModel. + + Args: + enabled: enabled + size: Size in bytes. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "sources": {"type": Sources}, + "destinations": {"type": Destinations}, + "encapsulation_gre_metadata_tx": {"type": bool}, + "header_remove_size": {"type": int}, + "access_group": {"type": AccessGroup}, + "rate_limit_per_ingress_chip": {"type": str}, + "rate_limit_per_egress_chip": {"type": str}, + "sample": {"type": int}, + "truncate": {"type": Truncate}, + "_custom_data": {"type": dict}, + } + name: str + """Session Name.""" + sources: Sources + """Subclass of AvdList with `SourcesItem` items.""" + destinations: Destinations + """Subclass of AvdList with `str` items.""" + encapsulation_gre_metadata_tx: bool | None + header_remove_size: int | None + """Number of bytes to remove from header.""" + access_group: AccessGroup + """Subclass of AvdModel.""" + rate_limit_per_ingress_chip: str | None + """ + Ratelimit and unit as string. + Examples: + "100000 bps" + "100 kbps" + "10 mbps" + """ + rate_limit_per_egress_chip: str | None + """ + Ratelimit and unit as string. + Examples: + "100000 bps" + "100 kbps" + "10 mbps" + """ + sample: int | None + truncate: Truncate + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + sources: Sources | UndefinedType = Undefined, + destinations: Destinations | UndefinedType = Undefined, + encapsulation_gre_metadata_tx: bool | None | UndefinedType = Undefined, + header_remove_size: int | None | UndefinedType = Undefined, + access_group: AccessGroup | UndefinedType = Undefined, + rate_limit_per_ingress_chip: str | None | UndefinedType = Undefined, + rate_limit_per_egress_chip: str | None | UndefinedType = Undefined, + sample: int | None | UndefinedType = Undefined, + truncate: Truncate | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MonitorSessionsItem. + + + Subclass of AvdModel. + + Args: + name: Session Name. + sources: Subclass of AvdList with `SourcesItem` items. + destinations: Subclass of AvdList with `str` items. + encapsulation_gre_metadata_tx: encapsulation_gre_metadata_tx + header_remove_size: Number of bytes to remove from header. + access_group: Subclass of AvdModel. + rate_limit_per_ingress_chip: + Ratelimit and unit as string. + Examples: # fmt: skip + "100000 bps" + "100 kbps" + "10 mbps" + rate_limit_per_egress_chip: + Ratelimit and unit as string. + Examples: # fmt: skip + "100000 bps" + "100 kbps" + "10 mbps" + sample: sample + truncate: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MonitorSessions(AvdList[MonitorSessionsItem]): + """Subclass of AvdList with `MonitorSessionsItem` items.""" + + MonitorSessions._item_type = MonitorSessionsItem + + class MonitorTelemetryInflux(AvdModel): + """Subclass of AvdModel.""" + + class DestinationsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "database": {"type": str}, + "data_retention_policy": {"type": str}, + "url": {"type": str}, + "username": {"type": str}, + "password": {"type": str}, + "password_type": {"type": str, "default": "7"}, + "_custom_data": {"type": dict}, + } + name: str + """InfluxDB connection name.""" + database: str | None + """Set name of the database.""" + data_retention_policy: str | None + url: str | None + """It only accepts http(s), udp and unix domain destination URL.""" + username: str | None + password: str | None + password_type: Literal["0", "7", "8a"] + """Default value: `"7"`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + database: str | None | UndefinedType = Undefined, + data_retention_policy: str | None | UndefinedType = Undefined, + url: str | None | UndefinedType = Undefined, + username: str | None | UndefinedType = Undefined, + password: str | None | UndefinedType = Undefined, + password_type: Literal["0", "7", "8a"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DestinationsItem. + + + Subclass of AvdModel. + + Args: + name: InfluxDB connection name. + database: Set name of the database. + data_retention_policy: data_retention_policy + url: It only accepts http(s), udp and unix domain destination URL. + username: username + password: password + password_type: password_type + _custom_data: _custom_data + + """ + + class Destinations(AvdIndexedList[str, DestinationsItem]): + """Subclass of AvdIndexedList with `DestinationsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Destinations._item_type = DestinationsItem + + class SourceSocketsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "connection_limit": {"type": int}, "url": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Label of the socket connection.""" + connection_limit: int | None + url: str | None + """It only accepts http(s), udp and unix domain socket URL.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + connection_limit: int | None | UndefinedType = Undefined, + url: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SourceSocketsItem. + + + Subclass of AvdModel. + + Args: + name: Label of the socket connection. + connection_limit: connection_limit + url: It only accepts http(s), udp and unix domain socket URL. + _custom_data: _custom_data + + """ + + class SourceSockets(AvdIndexedList[str, SourceSocketsItem]): + """Subclass of AvdIndexedList with `SourceSocketsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + SourceSockets._item_type = SourceSocketsItem + + class TagsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "value": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Key of the global tag pair.""" + value: str + """Value of the global tag pair.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + value: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TagsItem. + + + Subclass of AvdModel. + + Args: + name: Key of the global tag pair. + value: Value of the global tag pair. + _custom_data: _custom_data + + """ + + class Tags(AvdIndexedList[str, TagsItem]): + """Subclass of AvdIndexedList with `TagsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Tags._item_type = TagsItem + + _fields: ClassVar[dict] = { + "vrf": {"type": str}, + "destinations": {"type": Destinations}, + "source_group_standard_disabled": {"type": bool}, + "source_sockets": {"type": SourceSockets}, + "tags": {"type": Tags}, + "_custom_data": {"type": dict}, + } + vrf: str | None + destinations: Destinations + """ + Configure telemetry output destinations. + + Subclass of AvdIndexedList with `DestinationsItem` items. + Primary key is `name` (`str`). + """ + source_group_standard_disabled: bool | None + """Disable standard set of telemetry.""" + source_sockets: SourceSockets + """Subclass of AvdIndexedList with `SourceSocketsItem` items. Primary key is `name` (`str`).""" + tags: Tags + """ + Extra tags added to the telemetry output. + + Subclass of AvdIndexedList with `TagsItem` items. Primary + key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + vrf: str | None | UndefinedType = Undefined, + destinations: Destinations | UndefinedType = Undefined, + source_group_standard_disabled: bool | None | UndefinedType = Undefined, + source_sockets: SourceSockets | UndefinedType = Undefined, + tags: Tags | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MonitorTelemetryInflux. + + + Subclass of AvdModel. + + Args: + vrf: vrf + destinations: + Configure telemetry output destinations. + + Subclass of AvdIndexedList with `DestinationsItem` items. + Primary key is `name` (`str`). + source_group_standard_disabled: Disable standard set of telemetry. + source_sockets: Subclass of AvdIndexedList with `SourceSocketsItem` items. Primary key is `name` (`str`). + tags: + Extra tags added to the telemetry output. + + Subclass of AvdIndexedList with `TagsItem` items. Primary + key is `name` (`str`). + _custom_data: _custom_data + + """ + + class MonitorTelemetryPostcardPolicy(AvdModel): + """Subclass of AvdModel.""" + + class Ingress(AvdModel): + """Subclass of AvdModel.""" + + class Collection(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"source": {"type": str}, "destination": {"type": str}, "version": {"type": int}, "_custom_data": {"type": dict}} + source: str | None + """Source IP address of GRE tunnel.""" + destination: str | None + """Destination IP address of GRE tunnel.""" + version: Literal[1, 2] | None + """Postcard version.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source: str | None | UndefinedType = Undefined, + destination: str | None | UndefinedType = Undefined, + version: Literal[1, 2] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Collection. + + + Subclass of AvdModel. + + Args: + source: Source IP address of GRE tunnel. + destination: Destination IP address of GRE tunnel. + version: Postcard version. + _custom_data: _custom_data + + """ + + class Sample(AvdModel): + """Subclass of AvdModel.""" + + class TcpUdpChecksum(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"value": {"type": int}, "mask": {"type": str}, "_custom_data": {"type": dict}} + value: int | None + """TCP/UDP checksum or IP ID value.""" + mask: str | None + """16 bit hexadecimal mask for TCP/UDP or IP ID with at most 2 unset bits.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + value: int | None | UndefinedType = Undefined, + mask: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TcpUdpChecksum. + + + Subclass of AvdModel. + + Args: + value: TCP/UDP checksum or IP ID value. + mask: 16 bit hexadecimal mask for TCP/UDP or IP ID with at most 2 unset bits. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"rate": {"type": int}, "tcp_udp_checksum": {"type": TcpUdpChecksum}, "_custom_data": {"type": dict}} + rate: Literal[16384, 32768, 65536] | None + """Sampling rate. `rate` is preferred when both `rate` and `tcp_udp_checksum` are defined.""" + tcp_udp_checksum: TcpUdpChecksum + """ + TCP/UDP parameters. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + rate: Literal[16384, 32768, 65536] | None | UndefinedType = Undefined, + tcp_udp_checksum: TcpUdpChecksum | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Sample. + + + Subclass of AvdModel. + + Args: + rate: Sampling rate. `rate` is preferred when both `rate` and `tcp_udp_checksum` are defined. + tcp_udp_checksum: + TCP/UDP parameters. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"collection": {"type": Collection}, "sample": {"type": Sample}, "_custom_data": {"type": dict}} + collection: Collection + """ + Collector configuration. + + Subclass of AvdModel. + """ + sample: Sample + """ + Sampling parameters. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + collection: Collection | UndefinedType = Undefined, + sample: Sample | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ingress. + + + Subclass of AvdModel. + + Args: + collection: + Collector configuration. + + Subclass of AvdModel. + sample: + Sampling parameters. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MarkerVxlan(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "header_word_zero_bit": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool | None + """Enable vxlan marking using default bit 0.""" + header_word_zero_bit: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + header_word_zero_bit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MarkerVxlan. + + + Subclass of AvdModel. + + Args: + enabled: Enable vxlan marking using default bit 0. + header_word_zero_bit: header_word_zero_bit + _custom_data: _custom_data + + """ + + class ProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "ingress_sample_policy": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Profile name.""" + ingress_sample_policy: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + ingress_sample_policy: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ProfilesItem. + + + Subclass of AvdModel. + + Args: + name: Profile name. + ingress_sample_policy: ingress_sample_policy + _custom_data: _custom_data + + """ + + class Profiles(AvdIndexedList[str, ProfilesItem]): + """Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Profiles._item_type = ProfilesItem + + class SamplePoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + class MatchRulesItem(AvdModel): + """Subclass of AvdModel.""" + + class ProtocolsItem(AvdModel): + """Subclass of AvdModel.""" + + class SourcePorts(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + SourcePorts._item_type = str + + class DestinationPorts(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DestinationPorts._item_type = str + + _fields: ClassVar[dict] = { + "protocol": {"type": str}, + "source_ports": {"type": SourcePorts}, + "destination_ports": {"type": DestinationPorts}, + "_custom_data": {"type": dict}, + } + protocol: Literal["tcp", "udp"] + source_ports: SourcePorts + """ + A list of port numbers or port range or port name. Combination of port numbers or range and port + name is not supported on EOS. The port numbers should be in range of 0-65535. + e.g. + ["12", "14-20"] + ["www"] + + Subclass of AvdList with `str` items. + """ + destination_ports: DestinationPorts + """ + A list of port numbers or port range or port name. Combination of port numbers or range and port + name is not supported on EOS. The port numbers should be in range of 0-65535. + e.g. + ["12", "14-20", + "80"] + ["https"] + + Subclass of AvdList with `str` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + protocol: Literal["tcp", "udp"] | UndefinedType = Undefined, + source_ports: SourcePorts | UndefinedType = Undefined, + destination_ports: DestinationPorts | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ProtocolsItem. + + + Subclass of AvdModel. + + Args: + protocol: protocol + source_ports: + A list of port numbers or port range or port name. Combination of port numbers or range and port + name is not supported on EOS. The port numbers should be in range of 0-65535. + e.g. + ["12", "14-20"] + ["www"] + + Subclass of AvdList with `str` items. + destination_ports: + A list of port numbers or port range or port name. Combination of port numbers or range and port + name is not supported on EOS. The port numbers should be in range of 0-65535. + e.g. + ["12", "14-20", + "80"] + ["https"] + + Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class Protocols(AvdIndexedList[str, ProtocolsItem]): + """Subclass of AvdIndexedList with `ProtocolsItem` items. Primary key is `protocol` (`str`).""" + + _primary_key: ClassVar[str] = "protocol" + + Protocols._item_type = ProtocolsItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "type": {"type": str}, + "destination_prefix": {"type": str}, + "source_prefix": {"type": str}, + "protocols": {"type": Protocols}, + "_custom_data": {"type": dict}, + } + name: str + type: Literal["ipv4", "ipv6"] + """IP address version.""" + destination_prefix: str | None + """ + IPv4 Network/Mask or IPv6 Network/Mask. Host part of prefix must be zero. + eg. 10.3.3.0/24 + """ + source_prefix: str | None + """ + IPv4 Network/Mask or IPv6 Network/Mask. Host part of prefix must be zero. + eg. 10.3.3.0/24 + """ + protocols: Protocols + """Subclass of AvdIndexedList with `ProtocolsItem` items. Primary key is `protocol` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + type: Literal["ipv4", "ipv6"] | UndefinedType = Undefined, + destination_prefix: str | None | UndefinedType = Undefined, + source_prefix: str | None | UndefinedType = Undefined, + protocols: Protocols | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchRulesItem. + + + Subclass of AvdModel. + + Args: + name: name + type: IP address version. + destination_prefix: + IPv4 Network/Mask or IPv6 Network/Mask. Host part of prefix must be zero. + eg. 10.3.3.0/24 + source_prefix: + IPv4 Network/Mask or IPv6 Network/Mask. Host part of prefix must be zero. + eg. 10.3.3.0/24 + protocols: Subclass of AvdIndexedList with `ProtocolsItem` items. Primary key is `protocol` (`str`). + _custom_data: _custom_data + + """ + + class MatchRules(AvdIndexedList[str, MatchRulesItem]): + """Subclass of AvdIndexedList with `MatchRulesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + MatchRules._item_type = MatchRulesItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "match_rules": {"type": MatchRules}, "_custom_data": {"type": dict}} + name: str + match_rules: MatchRules + """Subclass of AvdIndexedList with `MatchRulesItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + match_rules: MatchRules | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SamplePoliciesItem. + + + Subclass of AvdModel. + + Args: + name: name + match_rules: Subclass of AvdIndexedList with `MatchRulesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class SamplePolicies(AvdIndexedList[str, SamplePoliciesItem]): + """Subclass of AvdIndexedList with `SamplePoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + SamplePolicies._item_type = SamplePoliciesItem + + _fields: ClassVar[dict] = { + "disabled": {"type": bool, "default": True}, + "ingress": {"type": Ingress}, + "marker_vxlan": {"type": MarkerVxlan}, + "profiles": {"type": Profiles}, + "sample_policies": {"type": SamplePolicies}, + "_custom_data": {"type": dict}, + } + disabled: bool + """ + Enable or disable the postcard telemetry feature. + + Default value: `True` + """ + ingress: Ingress + """Subclass of AvdModel.""" + marker_vxlan: MarkerVxlan + """Subclass of AvdModel.""" + profiles: Profiles + """ + Postcard telemetry profiles. + + Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is + `name` (`str`). + """ + sample_policies: SamplePolicies + """Subclass of AvdIndexedList with `SamplePoliciesItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + disabled: bool | UndefinedType = Undefined, + ingress: Ingress | UndefinedType = Undefined, + marker_vxlan: MarkerVxlan | UndefinedType = Undefined, + profiles: Profiles | UndefinedType = Undefined, + sample_policies: SamplePolicies | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MonitorTelemetryPostcardPolicy. + + + Subclass of AvdModel. + + Args: + disabled: Enable or disable the postcard telemetry feature. + ingress: Subclass of AvdModel. + marker_vxlan: Subclass of AvdModel. + profiles: + Postcard telemetry profiles. + + Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is + `name` (`str`). + sample_policies: Subclass of AvdIndexedList with `SamplePoliciesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class Mpls(AvdModel): + """Subclass of AvdModel.""" + + class Ldp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "interface_disabled_default": {"type": bool}, + "router_id": {"type": str}, + "shutdown": {"type": bool}, + "transport_address_interface": {"type": str}, + "_custom_data": {"type": dict}, + } + interface_disabled_default: bool | None + router_id: str | None + shutdown: bool | None + transport_address_interface: str | None + """Interface Name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interface_disabled_default: bool | None | UndefinedType = Undefined, + router_id: str | None | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + transport_address_interface: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ldp. + + + Subclass of AvdModel. + + Args: + interface_disabled_default: interface_disabled_default + router_id: router_id + shutdown: shutdown + transport_address_interface: Interface Name. + _custom_data: _custom_data + + """ + + class Icmp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "fragmentation_needed_tunneling": {"type": bool}, + "ttl_exceeded_tunneling": {"type": bool}, + "_custom_data": {"type": dict}, + } + fragmentation_needed_tunneling: bool | None + """Enables the MPLS tunneling of MTU exceeded ICMP replies (fragmentation needed, packet too big).""" + ttl_exceeded_tunneling: bool | None + """Enables the MPLS tunneling of TTL exceeded ICMP replies.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + fragmentation_needed_tunneling: bool | None | UndefinedType = Undefined, + ttl_exceeded_tunneling: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Icmp. + + + Subclass of AvdModel. + + Args: + fragmentation_needed_tunneling: Enables the MPLS tunneling of MTU exceeded ICMP replies (fragmentation needed, packet too big). + ttl_exceeded_tunneling: Enables the MPLS tunneling of TTL exceeded ICMP replies. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ip": {"type": bool}, "ldp": {"type": Ldp}, "icmp": {"type": Icmp}, "_custom_data": {"type": dict}} + ip: bool | None + ldp: Ldp + """Subclass of AvdModel.""" + icmp: Icmp + """ + Enables the LSRs to generate ICMP reply messages and deliver them to the originating host. + + Subclass + of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip: bool | None | UndefinedType = Undefined, + ldp: Ldp | UndefinedType = Undefined, + icmp: Icmp | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Mpls. + + + Subclass of AvdModel. + + Args: + ip: ip + ldp: Subclass of AvdModel. + icmp: + Enables the LSRs to generate ICMP reply messages and deliver them to the originating host. + + Subclass + of AvdModel. + _custom_data: _custom_data + + """ + + class Ntp(AvdModel): + """Subclass of AvdModel.""" + + class LocalInterface(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + """Source interface.""" + vrf: str | None + """VRF name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LocalInterface. + + + Subclass of AvdModel. + + Args: + name: Source interface. + vrf: VRF name. + _custom_data: _custom_data + + """ + + class ServersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "burst": {"type": bool}, + "iburst": {"type": bool}, + "key": {"type": int}, + "local_interface": {"type": str}, + "maxpoll": {"type": int}, + "minpoll": {"type": int}, + "preferred": {"type": bool}, + "version": {"type": int}, + "vrf": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str | None + """IP or hostname e.g., 2.2.2.55, 2001:db8::55, ie.pool.ntp.org.""" + burst: bool | None + iburst: bool | None + key: int | None + local_interface: str | None + """Source interface.""" + maxpoll: int | None + """Value of maxpoll between 3 - 17 (Logarithmic).""" + minpoll: int | None + """Value of minpoll between 3 - 17 (Logarithmic).""" + preferred: bool | None + version: int | None + vrf: str | None + """VRF name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + burst: bool | None | UndefinedType = Undefined, + iburst: bool | None | UndefinedType = Undefined, + key: int | None | UndefinedType = Undefined, + local_interface: str | None | UndefinedType = Undefined, + maxpoll: int | None | UndefinedType = Undefined, + minpoll: int | None | UndefinedType = Undefined, + preferred: bool | None | UndefinedType = Undefined, + version: int | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ServersItem. + + + Subclass of AvdModel. + + Args: + name: IP or hostname e.g., 2.2.2.55, 2001:db8::55, ie.pool.ntp.org. + burst: burst + iburst: iburst + key: key + local_interface: Source interface. + maxpoll: Value of maxpoll between 3 - 17 (Logarithmic). + minpoll: Value of minpoll between 3 - 17 (Logarithmic). + preferred: preferred + version: version + vrf: VRF name. + _custom_data: _custom_data + + """ + + class Servers(AvdList[ServersItem]): + """Subclass of AvdList with `ServersItem` items.""" + + Servers._item_type = ServersItem + + class AuthenticationKeysItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "hash_algorithm": {"type": str}, + "key": {"type": str}, + "key_type": {"type": str}, + "_custom_data": {"type": dict}, + } + id: int + """Key identifier.""" + hash_algorithm: Literal["md5", "sha1"] | None + key: str | None + """Obfuscated key.""" + key_type: Literal["0", "7", "8a"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + hash_algorithm: Literal["md5", "sha1"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + key_type: Literal["0", "7", "8a"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AuthenticationKeysItem. + + + Subclass of AvdModel. + + Args: + id: Key identifier. + hash_algorithm: hash_algorithm + key: Obfuscated key. + key_type: key_type + _custom_data: _custom_data + + """ + + class AuthenticationKeys(AvdIndexedList[int, AuthenticationKeysItem]): + """Subclass of AvdIndexedList with `AuthenticationKeysItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + AuthenticationKeys._item_type = AuthenticationKeysItem + + _fields: ClassVar[dict] = { + "local_interface": {"type": LocalInterface}, + "servers": {"type": Servers}, + "authenticate": {"type": bool}, + "authenticate_servers_only": {"type": bool}, + "authentication_keys": {"type": AuthenticationKeys}, + "trusted_keys": {"type": str}, + "_custom_data": {"type": dict}, + } + local_interface: LocalInterface + """Subclass of AvdModel.""" + servers: Servers + """Subclass of AvdList with `ServersItem` items.""" + authenticate: bool | None + authenticate_servers_only: bool | None + authentication_keys: AuthenticationKeys + """Subclass of AvdIndexedList with `AuthenticationKeysItem` items. Primary key is `id` (`int`).""" + trusted_keys: str | None + """List of trusted-keys as string ex. 10-12,15.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + local_interface: LocalInterface | UndefinedType = Undefined, + servers: Servers | UndefinedType = Undefined, + authenticate: bool | None | UndefinedType = Undefined, + authenticate_servers_only: bool | None | UndefinedType = Undefined, + authentication_keys: AuthenticationKeys | UndefinedType = Undefined, + trusted_keys: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ntp. + + + Subclass of AvdModel. + + Args: + local_interface: Subclass of AvdModel. + servers: Subclass of AvdList with `ServersItem` items. + authenticate: authenticate + authenticate_servers_only: authenticate_servers_only + authentication_keys: Subclass of AvdIndexedList with `AuthenticationKeysItem` items. Primary key is `id` (`int`). + trusted_keys: List of trusted-keys as string ex. 10-12,15. + _custom_data: _custom_data + + """ + + class PatchPanel(AvdModel): + """Subclass of AvdModel.""" + + class Connector(AvdModel): + """Subclass of AvdModel.""" + + class Interface(AvdModel): + """Subclass of AvdModel.""" + + class Patch(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"bgp_vpws_remote_failure_errdisable": {"type": bool}, "_custom_data": {"type": dict}} + bgp_vpws_remote_failure_errdisable: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + bgp_vpws_remote_failure_errdisable: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Patch. + + + Subclass of AvdModel. + + Args: + bgp_vpws_remote_failure_errdisable: bgp_vpws_remote_failure_errdisable + _custom_data: _custom_data + + """ + + class Recovery(AvdModel): + """Subclass of AvdModel.""" + + class ReviewDelay(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"min": {"type": int}, "max": {"type": int}, "_custom_data": {"type": dict}} + min: int + """Minimum delay.""" + max: int + """Maximum delay.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + min: int | UndefinedType = Undefined, + max: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ReviewDelay. + + + Subclass of AvdModel. + + Args: + min: Minimum delay. + max: Maximum delay. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"review_delay": {"type": ReviewDelay}, "_custom_data": {"type": dict}} + review_delay: ReviewDelay + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, review_delay: ReviewDelay | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Recovery. + + + Subclass of AvdModel. + + Args: + review_delay: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"patch": {"type": Patch}, "recovery": {"type": Recovery}, "_custom_data": {"type": dict}} + patch: Patch + """Subclass of AvdModel.""" + recovery: Recovery + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + patch: Patch | UndefinedType = Undefined, + recovery: Recovery | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Interface. + + + Subclass of AvdModel. + + Args: + patch: Subclass of AvdModel. + recovery: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"interface": {"type": Interface}, "_custom_data": {"type": dict}} + interface: Interface + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, interface: Interface | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Connector. + + + Subclass of AvdModel. + + Args: + interface: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PatchesItem(AvdModel): + """Subclass of AvdModel.""" + + class ConnectorsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"id": {"type": str}, "type": {"type": str}, "endpoint": {"type": str}, "_custom_data": {"type": dict}} + id: str + type: Literal["interface", "pseudowire"] + endpoint: str + """ + String with relevant endpoint depending on type. + Examples: + - "Ethernet1" + - "Ethernet1 dot1q vlan + 123" + - "bgp vpws TENANT_A pseudowire VPWS_PW_1" + - "ldp LDP_PW_1" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: str | UndefinedType = Undefined, + type: Literal["interface", "pseudowire"] | UndefinedType = Undefined, + endpoint: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ConnectorsItem. + + + Subclass of AvdModel. + + Args: + id: id + type: type + endpoint: + String with relevant endpoint depending on type. + Examples: # fmt: skip + - "Ethernet1" + - "Ethernet1 dot1q vlan + 123" + - "bgp vpws TENANT_A pseudowire VPWS_PW_1" + - "ldp LDP_PW_1" + _custom_data: _custom_data + + """ + + class Connectors(AvdIndexedList[str, ConnectorsItem]): + """Subclass of AvdIndexedList with `ConnectorsItem` items. Primary key is `id` (`str`).""" + + _primary_key: ClassVar[str] = "id" + + Connectors._item_type = ConnectorsItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "enabled": {"type": bool}, "connectors": {"type": Connectors}, "_custom_data": {"type": dict}} + name: str + enabled: bool | None + connectors: Connectors + """ + Must have exactly two connectors to a patch of which at least one must be of type "interface". + Subclass of AvdIndexedList with `ConnectorsItem` items. Primary key is `id` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + enabled: bool | None | UndefinedType = Undefined, + connectors: Connectors | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PatchesItem. + + + Subclass of AvdModel. + + Args: + name: name + enabled: enabled + connectors: + Must have exactly two connectors to a patch of which at least one must be of type "interface". + Subclass of AvdIndexedList with `ConnectorsItem` items. Primary key is `id` (`str`). + _custom_data: _custom_data + + """ + + class Patches(AvdIndexedList[str, PatchesItem]): + """Subclass of AvdIndexedList with `PatchesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Patches._item_type = PatchesItem + + _fields: ClassVar[dict] = {"connector": {"type": Connector}, "patches": {"type": Patches}, "_custom_data": {"type": dict}} + connector: Connector + """Subclass of AvdModel.""" + patches: Patches + """Subclass of AvdIndexedList with `PatchesItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + connector: Connector | UndefinedType = Undefined, + patches: Patches | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PatchPanel. + + + Subclass of AvdModel. + + Args: + connector: Subclass of AvdModel. + patches: Subclass of AvdIndexedList with `PatchesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class PeerFiltersItem(AvdModel): + """Subclass of AvdModel.""" + + class SequenceNumbersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"sequence": {"type": int}, "match": {"type": str}, "_custom_data": {"type": dict}} + sequence: int + """Sequence ID.""" + match: str + """ + Match as string. + Example: "as-range 1-100 result accept" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sequence: int | UndefinedType = Undefined, + match: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceNumbersItem. + + + Subclass of AvdModel. + + Args: + sequence: Sequence ID. + match: + Match as string. + Example: "as-range 1-100 result accept" + _custom_data: _custom_data + + """ + + class SequenceNumbers(AvdIndexedList[int, SequenceNumbersItem]): + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + + _primary_key: ClassVar[str] = "sequence" + + SequenceNumbers._item_type = SequenceNumbersItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "sequence_numbers": {"type": SequenceNumbers}, "_custom_data": {"type": dict}} + name: str + """Peer-filter Name.""" + sequence_numbers: SequenceNumbers + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + sequence_numbers: SequenceNumbers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeerFiltersItem. + + + Subclass of AvdModel. + + Args: + name: Peer-filter Name. + sequence_numbers: Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`). + _custom_data: _custom_data + + """ + + class PeerFilters(AvdIndexedList[str, PeerFiltersItem]): + """Subclass of AvdIndexedList with `PeerFiltersItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PeerFilters._item_type = PeerFiltersItem + + class Platform(AvdModel): + """Subclass of AvdModel.""" + + class Trident(AvdModel): + """Subclass of AvdModel.""" + + class L3(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"routing_mac_address_per_vlan": {"type": bool}, "_custom_data": {"type": dict}} + routing_mac_address_per_vlan: bool | None + """Enable bridging of packets with destination MAC being a Router MAC in VLANs without routing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, routing_mac_address_per_vlan: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + L3. + + + Subclass of AvdModel. + + Args: + routing_mac_address_per_vlan: Enable bridging of packets with destination MAC being a Router MAC in VLANs without routing. + _custom_data: _custom_data + + """ + + class Mmu(AvdModel): + """Subclass of AvdModel.""" + + class QueueProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class MulticastQueuesItem(AvdModel): + """Subclass of AvdModel.""" + + class Drop(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"precedence": {"type": int}, "threshold": {"type": str}, "_custom_data": {"type": dict}} + precedence: Literal[1, 2] + threshold: str + """ + Drop Threshold. This value may also be fractions. + Example: 7/8 or 3/4 or 1/2 + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + precedence: Literal[1, 2] | UndefinedType = Undefined, + threshold: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Drop. + + + Subclass of AvdModel. + + Args: + precedence: precedence + threshold: + Drop Threshold. This value may also be fractions. + Example: 7/8 or 3/4 or 1/2 + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "unit": {"type": str}, + "reserved": {"type": int}, + "threshold": {"type": str}, + "drop": {"type": Drop}, + "_custom_data": {"type": dict}, + } + id: int + unit: Literal["bytes", "cells"] | None + """Unit to be used for the reservation value. If not specified, default is bytes.""" + reserved: int | None + """ + Amount of memory that should be reserved for this + queue. + """ + threshold: str | None + """Dynamic Shared Memory threshold.""" + drop: Drop + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + unit: Literal["bytes", "cells"] | None | UndefinedType = Undefined, + reserved: int | None | UndefinedType = Undefined, + threshold: str | None | UndefinedType = Undefined, + drop: Drop | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MulticastQueuesItem. + + + Subclass of AvdModel. + + Args: + id: id + unit: Unit to be used for the reservation value. If not specified, default is bytes. + reserved: + Amount of memory that should be reserved for this + queue. + threshold: Dynamic Shared Memory threshold. + drop: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MulticastQueues(AvdIndexedList[int, MulticastQueuesItem]): + """Subclass of AvdIndexedList with `MulticastQueuesItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + MulticastQueues._item_type = MulticastQueuesItem + + class UnicastQueuesItem(AvdModel): + """Subclass of AvdModel.""" + + class Drop(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"precedence": {"type": int}, "threshold": {"type": str}, "_custom_data": {"type": dict}} + precedence: Literal[1, 2] + threshold: str + """ + Drop Threshold. This value may also be fractions. + Example: 7/8 or 3/4 or 1/2 + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + precedence: Literal[1, 2] | UndefinedType = Undefined, + threshold: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Drop. + + + Subclass of AvdModel. + + Args: + precedence: precedence + threshold: + Drop Threshold. This value may also be fractions. + Example: 7/8 or 3/4 or 1/2 + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "unit": {"type": str}, + "reserved": {"type": int}, + "threshold": {"type": str}, + "drop": {"type": Drop}, + "_custom_data": {"type": dict}, + } + id: int + unit: Literal["bytes", "cells"] | None + """Unit to be used for the reservation value. If not specified, default is bytes.""" + reserved: int | None + """ + Amount of memory that should be reserved for this + queue. + """ + threshold: str | None + """Dynamic Shared Memory threshold.""" + drop: Drop + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + unit: Literal["bytes", "cells"] | None | UndefinedType = Undefined, + reserved: int | None | UndefinedType = Undefined, + threshold: str | None | UndefinedType = Undefined, + drop: Drop | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + UnicastQueuesItem. + + + Subclass of AvdModel. + + Args: + id: id + unit: Unit to be used for the reservation value. If not specified, default is bytes. + reserved: + Amount of memory that should be reserved for this + queue. + threshold: Dynamic Shared Memory threshold. + drop: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class UnicastQueues(AvdIndexedList[int, UnicastQueuesItem]): + """Subclass of AvdIndexedList with `UnicastQueuesItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + UnicastQueues._item_type = UnicastQueuesItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "multicast_queues": {"type": MulticastQueues}, + "unicast_queues": {"type": UnicastQueues}, + "_custom_data": {"type": dict}, + } + name: str + multicast_queues: MulticastQueues + """Subclass of AvdIndexedList with `MulticastQueuesItem` items. Primary key is `id` (`int`).""" + unicast_queues: UnicastQueues + """Subclass of AvdIndexedList with `UnicastQueuesItem` items. Primary key is `id` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + multicast_queues: MulticastQueues | UndefinedType = Undefined, + unicast_queues: UnicastQueues | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + QueueProfilesItem. + + + Subclass of AvdModel. + + Args: + name: name + multicast_queues: Subclass of AvdIndexedList with `MulticastQueuesItem` items. Primary key is `id` (`int`). + unicast_queues: Subclass of AvdIndexedList with `UnicastQueuesItem` items. Primary key is `id` (`int`). + _custom_data: _custom_data + + """ + + class QueueProfiles(AvdIndexedList[str, QueueProfilesItem]): + """Subclass of AvdIndexedList with `QueueProfilesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + QueueProfiles._item_type = QueueProfilesItem + + _fields: ClassVar[dict] = {"active_profile": {"type": str}, "queue_profiles": {"type": QueueProfiles}, "_custom_data": {"type": dict}} + active_profile: str | None + """The queue profile to be applied to the platform.""" + queue_profiles: QueueProfiles + """Subclass of AvdIndexedList with `QueueProfilesItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + active_profile: str | None | UndefinedType = Undefined, + queue_profiles: QueueProfiles | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Mmu. + + + Subclass of AvdModel. + + Args: + active_profile: The queue profile to be applied to the platform. + queue_profiles: Subclass of AvdIndexedList with `QueueProfilesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"forwarding_table_partition": {"type": str}, "l3": {"type": L3}, "mmu": {"type": Mmu}, "_custom_data": {"type": dict}} + forwarding_table_partition: str | None + l3: L3 + """Subclass of AvdModel.""" + mmu: Mmu + """ + Memory Management Unit settings. + + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + forwarding_table_partition: str | None | UndefinedType = Undefined, + l3: L3 | UndefinedType = Undefined, + mmu: Mmu | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Trident. + + + Subclass of AvdModel. + + Args: + forwarding_table_partition: forwarding_table_partition + l3: Subclass of AvdModel. + mmu: + Memory Management Unit settings. + + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Sand(AvdModel): + """Subclass of AvdModel.""" + + class QosMapsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"traffic_class": {"type": int}, "to_network_qos": {"type": int}, "_custom_data": {"type": dict}} + traffic_class: int | None + to_network_qos: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + traffic_class: int | None | UndefinedType = Undefined, + to_network_qos: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + QosMapsItem. + + + Subclass of AvdModel. + + Args: + traffic_class: traffic_class + to_network_qos: to_network_qos + _custom_data: _custom_data + + """ + + class QosMaps(AvdList[QosMapsItem]): + """Subclass of AvdList with `QosMapsItem` items.""" + + QosMaps._item_type = QosMapsItem + + class Lag(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"hardware_only": {"type": bool}, "mode": {"type": str}, "_custom_data": {"type": dict}} + hardware_only: bool | None + mode: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hardware_only: bool | None | UndefinedType = Undefined, + mode: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Lag. + + + Subclass of AvdModel. + + Args: + hardware_only: hardware_only + mode: mode + _custom_data: _custom_data + + """ + + class MulticastReplication(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"default": {"type": str}, "_custom_data": {"type": dict}} + default: Literal["ingress", "egress"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + default: Literal["ingress", "egress"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MulticastReplication. + + + Subclass of AvdModel. + + Args: + default: default + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "qos_maps": {"type": QosMaps}, + "lag": {"type": Lag}, + "forwarding_mode": {"type": str}, + "multicast_replication": {"type": MulticastReplication}, + "mdb_profile": {"type": str}, + "_custom_data": {"type": dict}, + } + qos_maps: QosMaps + """Subclass of AvdList with `QosMapsItem` items.""" + lag: Lag + """Subclass of AvdModel.""" + forwarding_mode: str | None + multicast_replication: MulticastReplication + """Subclass of AvdModel.""" + mdb_profile: Literal["balanced", "balanced-xl", "l3", "l3-xl", "l3-xxl", "l3-xxxl"] | None + """Sand platforms MDB Profile configuration. Note: l3-xxxl does not support MLAG.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + qos_maps: QosMaps | UndefinedType = Undefined, + lag: Lag | UndefinedType = Undefined, + forwarding_mode: str | None | UndefinedType = Undefined, + multicast_replication: MulticastReplication | UndefinedType = Undefined, + mdb_profile: Literal["balanced", "balanced-xl", "l3", "l3-xl", "l3-xxl", "l3-xxxl"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Sand. + + + Subclass of AvdModel. + + Args: + qos_maps: Subclass of AvdList with `QosMapsItem` items. + lag: Subclass of AvdModel. + forwarding_mode: forwarding_mode + multicast_replication: Subclass of AvdModel. + mdb_profile: Sand platforms MDB Profile configuration. Note: l3-xxxl does not support MLAG. + _custom_data: _custom_data + + """ + + class Sfe(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"data_plane_cpu_allocation_max": {"type": int}, "_custom_data": {"type": dict}} + data_plane_cpu_allocation_max: int | None + """Maximum number of CPUs used for data plane traffic forwarding.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, data_plane_cpu_allocation_max: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Sfe. + + + Subclass of AvdModel. + + Args: + data_plane_cpu_allocation_max: Maximum number of CPUs used for data plane traffic forwarding. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"trident": {"type": Trident}, "sand": {"type": Sand}, "sfe": {"type": Sfe}, "_custom_data": {"type": dict}} + trident: Trident + """Subclass of AvdModel.""" + sand: Sand + """ + Most of the platform sand options are hardware dependent and optional. + + Subclass of AvdModel. + """ + sfe: Sfe + """ + Sfe (Software Forwarding Engine) settings. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + trident: Trident | UndefinedType = Undefined, + sand: Sand | UndefinedType = Undefined, + sfe: Sfe | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Platform. + + + Subclass of AvdModel. + + Args: + trident: Subclass of AvdModel. + sand: + Most of the platform sand options are hardware dependent and optional. + + Subclass of AvdModel. + sfe: + Sfe (Software Forwarding Engine) settings. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Poe(AvdModel): + """Subclass of AvdModel.""" + + class Reboot(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"action": {"type": str}, "_custom_data": {"type": dict}} + action: Literal["power-off", "maintain"] | None + """PoE action for interface. By default in EOS, reboot action is set to power-off.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["power-off", "maintain"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Reboot. + + + Subclass of AvdModel. + + Args: + action: PoE action for interface. By default in EOS, reboot action is set to power-off. + _custom_data: _custom_data + + """ + + class InterfaceShutdown(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"action": {"type": str}, "_custom_data": {"type": dict}} + action: Literal["power-off", "maintain"] | None + """PoE action for interface. By default in EOS, interface shutdown action is set to maintain.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["power-off", "maintain"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + InterfaceShutdown. + + + Subclass of AvdModel. + + Args: + action: PoE action for interface. By default in EOS, interface shutdown action is set to maintain. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"reboot": {"type": Reboot}, "interface_shutdown": {"type": InterfaceShutdown}, "_custom_data": {"type": dict}} + reboot: Reboot + """ + Set the global PoE power behavior for PoE ports when the system is rebooted. + + Subclass of AvdModel. + """ + interface_shutdown: InterfaceShutdown + """ + Set the global PoE power behavior for PoE ports when ports are admin down. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + reboot: Reboot | UndefinedType = Undefined, + interface_shutdown: InterfaceShutdown | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Poe. + + + Subclass of AvdModel. + + Args: + reboot: + Set the global PoE power behavior for PoE ports when the system is rebooted. + + Subclass of AvdModel. + interface_shutdown: + Set the global PoE power behavior for PoE ports when ports are admin down. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PolicyMaps(AvdModel): + """Subclass of AvdModel.""" + + class PbrItem(AvdModel): + """Subclass of AvdModel.""" + + class ClassesItem(AvdModel): + """Subclass of AvdModel.""" + + class Set(AvdModel): + """Subclass of AvdModel.""" + + class Nexthop(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ip_address": {"type": str}, "recursive": {"type": bool}, "_custom_data": {"type": dict}} + ip_address: str | None + """IPv4 or IPv6 Address.""" + recursive: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | None | UndefinedType = Undefined, + recursive: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Nexthop. + + + Subclass of AvdModel. + + Args: + ip_address: IPv4 or IPv6 Address. + recursive: recursive + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"nexthop": {"type": Nexthop}, "_custom_data": {"type": dict}} + nexthop: Nexthop + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, nexthop: Nexthop | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Set. + + + Subclass of AvdModel. + + Args: + nexthop: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "index": {"type": int}, + "drop": {"type": bool}, + "set": {"type": Set}, + "_custom_data": {"type": dict}, + } + name: str + """Class Name.""" + index: int | None + drop: bool | None + """'drop' and 'set' are mutually exclusive.""" + set: Set + """ + Set Nexthop + 'drop' and 'set' are mutually exclusive. + + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + index: int | None | UndefinedType = Undefined, + drop: bool | None | UndefinedType = Undefined, + set: Set | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ClassesItem. + + + Subclass of AvdModel. + + Args: + name: Class Name. + index: index + drop: 'drop' and 'set' are mutually exclusive. + set: + Set Nexthop + 'drop' and 'set' are mutually exclusive. + + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Classes(AvdIndexedList[str, ClassesItem]): + """Subclass of AvdIndexedList with `ClassesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Classes._item_type = ClassesItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "classes": {"type": Classes}, "_custom_data": {"type": dict}} + name: str + """Policy-Map Name.""" + classes: Classes + """Subclass of AvdIndexedList with `ClassesItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + classes: Classes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PbrItem. + + + Subclass of AvdModel. + + Args: + name: Policy-Map Name. + classes: Subclass of AvdIndexedList with `ClassesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class Pbr(AvdIndexedList[str, PbrItem]): + """Subclass of AvdIndexedList with `PbrItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Pbr._item_type = PbrItem + + class QosItem(AvdModel): + """Subclass of AvdModel.""" + + class ClassesItem(AvdModel): + """Subclass of AvdModel.""" + + class Set(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "cos": {"type": int}, + "dscp": {"type": str}, + "traffic_class": {"type": int}, + "drop_precedence": {"type": int}, + "_custom_data": {"type": dict}, + } + cos: int | None + dscp: str | None + traffic_class: int | None + drop_precedence: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + cos: int | None | UndefinedType = Undefined, + dscp: str | None | UndefinedType = Undefined, + traffic_class: int | None | UndefinedType = Undefined, + drop_precedence: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Set. + + + Subclass of AvdModel. + + Args: + cos: cos + dscp: dscp + traffic_class: traffic_class + drop_precedence: drop_precedence + _custom_data: _custom_data + + """ + + class Police(AvdModel): + """Subclass of AvdModel.""" + + class Action(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"type": {"type": str}, "dscp_value": {"type": str}, "_custom_data": {"type": dict}} + type: Literal["dscp", "drop-precedence"] | None + """Set action for policed traffic.""" + dscp_value: str | None + """Set when action.type is set to "dscp".""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + type: Literal["dscp", "drop-precedence"] | None | UndefinedType = Undefined, + dscp_value: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Action. + + + Subclass of AvdModel. + + Args: + type: Set action for policed traffic. + dscp_value: Set when action.type is set to "dscp". + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "rate": {"type": int}, + "rate_unit": {"type": str, "default": "bps"}, + "rate_burst_size": {"type": int}, + "rate_burst_size_unit": {"type": str, "default": "bytes"}, + "action": {"type": Action}, + "higher_rate": {"type": int}, + "higher_rate_unit": {"type": str, "default": "bps"}, + "higher_rate_burst_size": {"type": int}, + "higher_rate_burst_size_unit": {"type": str, "default": "bytes"}, + "_custom_data": {"type": dict}, + } + rate: int | None + """ + Specify rate. + Range in kbps <8-200000000>. + """ + rate_unit: Literal["bps", "kbps", "mbps", "pps"] + """Default value: `"bps"`""" + rate_burst_size: int | None + """Range in bytes <256-128000000>.""" + rate_burst_size_unit: Literal["bytes", "kbytes", "mbytes", "packets"] + """Default value: `"bytes"`""" + action: Action + """Subclass of AvdModel.""" + higher_rate: int | None + """ + Specify higher rate. + Range in kbps . + """ + higher_rate_unit: Literal["bps", "kbps", "mbps", "pps"] + """Default value: `"bps"`""" + higher_rate_burst_size: int | None + """Range in bytes <256-128000000>.""" + higher_rate_burst_size_unit: Literal["bytes", "kbytes", "mbytes", "packets"] + """Default value: `"bytes"`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + rate: int | None | UndefinedType = Undefined, + rate_unit: Literal["bps", "kbps", "mbps", "pps"] | UndefinedType = Undefined, + rate_burst_size: int | None | UndefinedType = Undefined, + rate_burst_size_unit: Literal["bytes", "kbytes", "mbytes", "packets"] | UndefinedType = Undefined, + action: Action | UndefinedType = Undefined, + higher_rate: int | None | UndefinedType = Undefined, + higher_rate_unit: Literal["bps", "kbps", "mbps", "pps"] | UndefinedType = Undefined, + higher_rate_burst_size: int | None | UndefinedType = Undefined, + higher_rate_burst_size_unit: Literal["bytes", "kbytes", "mbytes", "packets"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Police. + + + Subclass of AvdModel. + + Args: + rate: + Specify rate. + Range in kbps <8-200000000>. + rate_unit: rate_unit + rate_burst_size: Range in bytes <256-128000000>. + rate_burst_size_unit: rate_burst_size_unit + action: Subclass of AvdModel. + higher_rate: + Specify higher rate. + Range in kbps . + higher_rate_unit: higher_rate_unit + higher_rate_burst_size: Range in bytes <256-128000000>. + higher_rate_burst_size_unit: higher_rate_burst_size_unit + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"name": {"type": str}, "set": {"type": Set}, "police": {"type": Police}, "_custom_data": {"type": dict}} + name: str + """Class Name.""" + set: Set + """Subclass of AvdModel.""" + police: Police + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + set: Set | UndefinedType = Undefined, + police: Police | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ClassesItem. + + + Subclass of AvdModel. + + Args: + name: Class Name. + set: Subclass of AvdModel. + police: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Classes(AvdIndexedList[str, ClassesItem]): + """Subclass of AvdIndexedList with `ClassesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Classes._item_type = ClassesItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "classes": {"type": Classes}, "_custom_data": {"type": dict}} + name: str + """Policy-Map Name.""" + classes: Classes + """Subclass of AvdIndexedList with `ClassesItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + classes: Classes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + QosItem. + + + Subclass of AvdModel. + + Args: + name: Policy-Map Name. + classes: Subclass of AvdIndexedList with `ClassesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class Qos(AvdIndexedList[str, QosItem]): + """Subclass of AvdIndexedList with `QosItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Qos._item_type = QosItem + + class CoppSystemPolicy(AvdModel): + """Subclass of AvdModel.""" + + class ClassesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "shape": {"type": int}, + "bandwidth": {"type": int}, + "rate_unit": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + shape: int | None + """Maximum rate limit.""" + bandwidth: int | None + """Minimum bandwidth.""" + rate_unit: Literal["pps", "kbps"] | None + """The `rate_unit` must be defined for `shape` and `bandwidth`.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + shape: int | None | UndefinedType = Undefined, + bandwidth: int | None | UndefinedType = Undefined, + rate_unit: Literal["pps", "kbps"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ClassesItem. + + + Subclass of AvdModel. + + Args: + name: name + shape: Maximum rate limit. + bandwidth: Minimum bandwidth. + rate_unit: The `rate_unit` must be defined for `shape` and `bandwidth`. + _custom_data: _custom_data + + """ + + class Classes(AvdIndexedList[str, ClassesItem]): + """Subclass of AvdIndexedList with `ClassesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Classes._item_type = ClassesItem + + _fields: ClassVar[dict] = {"classes": {"type": Classes}, "_custom_data": {"type": dict}} + classes: Classes + """Subclass of AvdIndexedList with `ClassesItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, classes: Classes | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + CoppSystemPolicy. + + + Subclass of AvdModel. + + Args: + classes: Subclass of AvdIndexedList with `ClassesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"pbr": {"type": Pbr}, "qos": {"type": Qos}, "copp_system_policy": {"type": CoppSystemPolicy}, "_custom_data": {"type": dict}} + pbr: Pbr + """ + PBR Policy-Maps. + + Subclass of AvdIndexedList with `PbrItem` items. Primary key is `name` (`str`). + """ + qos: Qos + """ + QOS Policy-Maps. + + Subclass of AvdIndexedList with `QosItem` items. Primary key is `name` (`str`). + """ + copp_system_policy: CoppSystemPolicy + """ + Control-plane policy configuration. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + pbr: Pbr | UndefinedType = Undefined, + qos: Qos | UndefinedType = Undefined, + copp_system_policy: CoppSystemPolicy | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PolicyMaps. + + + Subclass of AvdModel. + + Args: + pbr: + PBR Policy-Maps. + + Subclass of AvdIndexedList with `PbrItem` items. Primary key is `name` (`str`). + qos: + QOS Policy-Maps. + + Subclass of AvdIndexedList with `QosItem` items. Primary key is `name` (`str`). + copp_system_policy: + Control-plane policy configuration. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PortChannelInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Logging(AvdModel): + """Subclass of AvdModel.""" + + class Event(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"link_status": {"type": bool}, "storm_control_discards": {"type": bool}, "_custom_data": {"type": dict}} + link_status: bool | None + storm_control_discards: bool | None + """Discards due to storm-control.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + link_status: bool | None | UndefinedType = Undefined, + storm_control_discards: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Event. + + + Subclass of AvdModel. + + Args: + link_status: link_status + storm_control_discards: Discards due to storm-control. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"event": {"type": Event}, "_custom_data": {"type": dict}} + event: Event + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, event: Event | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Logging. + + + Subclass of AvdModel. + + Args: + event: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class EncapsulationDot1q(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"vlan": {"type": int}, "inner_vlan": {"type": int}, "_custom_data": {"type": dict}} + vlan: int + """VLAD ID.""" + inner_vlan: int | None + """Inner VLAN ID. This setting can only be applied to sub-interfaces on EOS.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + vlan: int | UndefinedType = Undefined, + inner_vlan: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EncapsulationDot1q. + + + Subclass of AvdModel. + + Args: + vlan: VLAD ID. + inner_vlan: Inner VLAN ID. This setting can only be applied to sub-interfaces on EOS. + _custom_data: _custom_data + + """ + + class EncapsulationVlan(AvdModel): + """Subclass of AvdModel.""" + + class Client(AvdModel): + """Subclass of AvdModel.""" + + class Dot1q(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"vlan": {"type": int}, "outer": {"type": int}, "inner": {"type": int}, "_custom_data": {"type": dict}} + vlan: int | None + """Client VLAN ID.""" + outer: int | None + """Client Outer VLAN ID.""" + inner: int | None + """Client Inner VLAN ID.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + vlan: int | None | UndefinedType = Undefined, + outer: int | None | UndefinedType = Undefined, + inner: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dot1q. + + + Subclass of AvdModel. + + Args: + vlan: Client VLAN ID. + outer: Client Outer VLAN ID. + inner: Client Inner VLAN ID. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "dot1q": {"type": Dot1q}, + "unmatched": {"type": bool}, + "encapsulation": {"type": str}, + "vlan": {"type": int}, + "outer_vlan": {"type": int}, + "inner_vlan": {"type": int}, + "inner_encapsulation": {"type": str}, + "_custom_data": {"type": dict}, + } + dot1q: Dot1q + """Subclass of AvdModel.""" + unmatched: bool | None + encapsulation: Literal["dot1q", "dot1ad", "unmatched", "untagged"] | None + vlan: int | None + """Client VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: unmatched`.""" + outer_vlan: int | None + """Client Outer VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: unmatched`.""" + inner_vlan: int | None + """Client Inner VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: unmatched`.""" + inner_encapsulation: Literal["dot1q", "dot1ad"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dot1q: Dot1q | UndefinedType = Undefined, + unmatched: bool | None | UndefinedType = Undefined, + encapsulation: Literal["dot1q", "dot1ad", "unmatched", "untagged"] | None | UndefinedType = Undefined, + vlan: int | None | UndefinedType = Undefined, + outer_vlan: int | None | UndefinedType = Undefined, + inner_vlan: int | None | UndefinedType = Undefined, + inner_encapsulation: Literal["dot1q", "dot1ad"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Client. + + + Subclass of AvdModel. + + Args: + dot1q: Subclass of AvdModel. + unmatched: unmatched + encapsulation: encapsulation + vlan: Client VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: unmatched`. + outer_vlan: Client Outer VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: unmatched`. + inner_vlan: Client Inner VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: unmatched`. + inner_encapsulation: inner_encapsulation + _custom_data: _custom_data + + """ + + class Network(AvdModel): + """Subclass of AvdModel.""" + + class Dot1q(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"vlan": {"type": int}, "outer": {"type": int}, "inner": {"type": int}, "_custom_data": {"type": dict}} + vlan: int | None + """Network VLAN ID.""" + outer: int | None + """Network Outer VLAN ID.""" + inner: int | None + """Network Inner VLAN ID.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + vlan: int | None | UndefinedType = Undefined, + outer: int | None | UndefinedType = Undefined, + inner: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dot1q. + + + Subclass of AvdModel. + + Args: + vlan: Network VLAN ID. + outer: Network Outer VLAN ID. + inner: Network Inner VLAN ID. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "dot1q": {"type": Dot1q}, + "client": {"type": bool}, + "encapsulation": {"type": str}, + "vlan": {"type": int}, + "outer_vlan": {"type": int}, + "inner_vlan": {"type": int}, + "inner_encapsulation": {"type": str}, + "_custom_data": {"type": dict}, + } + dot1q: Dot1q + """Subclass of AvdModel.""" + client: bool | None + encapsulation: Literal["dot1q", "dot1ad", "client", "client inner", "untagged"] | None + """ + `untagged` (no encapsulation) is applicable for `untagged` client only. + `client` and `client inner` + (retain client encapsulation) is not applicable for `untagged` client. + """ + vlan: int | None + """Network VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: client`.""" + outer_vlan: int | None + """Network outer VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: client`.""" + inner_vlan: int | None + """Network inner VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: client`.""" + inner_encapsulation: Literal["dot1q", "dot1ad"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dot1q: Dot1q | UndefinedType = Undefined, + client: bool | None | UndefinedType = Undefined, + encapsulation: Literal["dot1q", "dot1ad", "client", "client inner", "untagged"] | None | UndefinedType = Undefined, + vlan: int | None | UndefinedType = Undefined, + outer_vlan: int | None | UndefinedType = Undefined, + inner_vlan: int | None | UndefinedType = Undefined, + inner_encapsulation: Literal["dot1q", "dot1ad"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Network. + + + Subclass of AvdModel. + + Args: + dot1q: Subclass of AvdModel. + client: client + encapsulation: + `untagged` (no encapsulation) is applicable for `untagged` client only. + `client` and `client inner` + (retain client encapsulation) is not applicable for `untagged` client. + vlan: Network VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: client`. + outer_vlan: Network outer VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: client`. + inner_vlan: Network inner VLAN ID. Not applicable for `encapsulation: untagged` or `encapsulation: client`. + inner_encapsulation: inner_encapsulation + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"client": {"type": Client}, "network": {"type": Network}, "_custom_data": {"type": dict}} + client: Client + """Subclass of AvdModel.""" + network: Network + """ + Network encapsulation are all optional, and skipped if using client unmatched. + + Subclass of + AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + client: Client | UndefinedType = Undefined, + network: Network | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EncapsulationVlan. + + + Subclass of AvdModel. + + Args: + client: Subclass of AvdModel. + network: + Network encapsulation are all optional, and skipped if using client unmatched. + + Subclass of + AvdModel. + _custom_data: _custom_data + + """ + + class LinkTrackingGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "direction": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Group name.""" + direction: Literal["upstream", "downstream"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + direction: Literal["upstream", "downstream"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkTrackingGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Group name. + direction: direction + _custom_data: _custom_data + + """ + + class LinkTrackingGroups(AvdIndexedList[str, LinkTrackingGroupsItem]): + """Subclass of AvdIndexedList with `LinkTrackingGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + LinkTrackingGroups._item_type = LinkTrackingGroupsItem + + class LinkTracking(AvdModel): + """Subclass of AvdModel.""" + + class Groups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Groups._item_type = str + + _fields: ClassVar[dict] = {"direction": {"type": str}, "groups": {"type": Groups}, "_custom_data": {"type": dict}} + direction: Literal["upstream", "downstream"] | None + groups: Groups + """ + Link state group(s) an interface belongs to. + + Subclass of AvdList with `str` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction: Literal["upstream", "downstream"] | None | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkTracking. + + + Subclass of AvdModel. + + Args: + direction: direction + groups: + Link state group(s) an interface belongs to. + + Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class Phone(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"trunk": {"type": str}, "vlan": {"type": int}, "_custom_data": {"type": dict}} + trunk: Literal["tagged", "untagged"] | None + vlan: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + trunk: Literal["tagged", "untagged"] | None | UndefinedType = Undefined, + vlan: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Phone. + + + Subclass of AvdModel. + + Args: + trunk: trunk + vlan: vlan + _custom_data: _custom_data + + """ + + class L2Protocol(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"encapsulation_dot1q_vlan": {"type": int}, "forwarding_profile": {"type": str}, "_custom_data": {"type": dict}} + encapsulation_dot1q_vlan: int | None + """Vlan tag to configure on sub-interface.""" + forwarding_profile: str | None + """L2 protocol forwarding profile.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + encapsulation_dot1q_vlan: int | None | UndefinedType = Undefined, + forwarding_profile: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L2Protocol. + + + Subclass of AvdModel. + + Args: + encapsulation_dot1q_vlan: Vlan tag to configure on sub-interface. + forwarding_profile: L2 protocol forwarding profile. + _custom_data: _custom_data + + """ + + class TrunkGroups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + TrunkGroups._item_type = str + + class Qos(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"trust": {"type": str}, "dscp": {"type": int}, "cos": {"type": int}, "_custom_data": {"type": dict}} + trust: Literal["dscp", "cos", "disabled"] | None + dscp: int | None + """DSCP value.""" + cos: int | None + """COS value.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + trust: Literal["dscp", "cos", "disabled"] | None | UndefinedType = Undefined, + dscp: int | None | UndefinedType = Undefined, + cos: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Qos. + + + Subclass of AvdModel. + + Args: + trust: trust + dscp: DSCP value. + cos: COS value. + _custom_data: _custom_data + + """ + + class Bfd(AvdModel): + """Subclass of AvdModel.""" + + class PerLink(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "rfc_7130": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + rfc_7130: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + rfc_7130: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PerLink. + + + Subclass of AvdModel. + + Args: + enabled: enabled + rfc_7130: rfc_7130 + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "echo": {"type": bool}, + "interval": {"type": int}, + "min_rx": {"type": int}, + "multiplier": {"type": int}, + "neighbor": {"type": str}, + "per_link": {"type": PerLink}, + "_custom_data": {"type": dict}, + } + echo: bool | None + interval: int | None + """Interval in milliseconds.""" + min_rx: int | None + """Rate in milliseconds.""" + multiplier: int | None + neighbor: str | None + """ + IPv4 or IPv6 address. When the Port-channel is a L2 interface, a local L3 BFD address + (router_bfd.local_address) has to be defined globally on the switch. + """ + per_link: PerLink + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + echo: bool | None | UndefinedType = Undefined, + interval: int | None | UndefinedType = Undefined, + min_rx: int | None | UndefinedType = Undefined, + multiplier: int | None | UndefinedType = Undefined, + neighbor: str | None | UndefinedType = Undefined, + per_link: PerLink | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bfd. + + + Subclass of AvdModel. + + Args: + echo: echo + interval: Interval in milliseconds. + min_rx: Rate in milliseconds. + multiplier: multiplier + neighbor: + IPv4 or IPv6 address. When the Port-channel is a L2 interface, a local L3 BFD address + (router_bfd.local_address) has to be defined globally on the switch. + per_link: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class ServicePolicy(AvdModel): + """Subclass of AvdModel.""" + + class Pbr(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"input": {"type": str}, "_custom_data": {"type": dict}} + input: str | None + """Policy Based Routing Policy-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, input: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Pbr. + + + Subclass of AvdModel. + + Args: + input: Policy Based Routing Policy-map name. + _custom_data: _custom_data + + """ + + class Qos(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"input": {"type": str}, "_custom_data": {"type": dict}} + input: str + """Quality of Service Policy-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, input: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Qos. + + + Subclass of AvdModel. + + Args: + input: Quality of Service Policy-map name. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"pbr": {"type": Pbr}, "qos": {"type": Qos}, "_custom_data": {"type": dict}} + pbr: Pbr + """Subclass of AvdModel.""" + qos: Qos + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + pbr: Pbr | UndefinedType = Undefined, + qos: Qos | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ServicePolicy. + + + Subclass of AvdModel. + + Args: + pbr: Subclass of AvdModel. + qos: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Mpls(AvdModel): + """Subclass of AvdModel.""" + + class Ldp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interface": {"type": bool}, "igp_sync": {"type": bool}, "_custom_data": {"type": dict}} + interface: bool | None + igp_sync: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interface: bool | None | UndefinedType = Undefined, + igp_sync: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ldp. + + + Subclass of AvdModel. + + Args: + interface: interface + igp_sync: igp_sync + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ip": {"type": bool}, "ldp": {"type": Ldp}, "_custom_data": {"type": dict}} + ip: bool | None + ldp: Ldp + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip: bool | None | UndefinedType = Undefined, + ldp: Ldp | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Mpls. + + + Subclass of AvdModel. + + Args: + ip: ip + ldp: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class VlanTranslationsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "field_from": {"type": str}, + "to": {"type": int}, + "direction": {"type": str, "default": "both"}, + "_custom_data": {"type": dict}, + } + _field_to_key_map: ClassVar[dict] = {"field_from": "from"} + _key_to_field_map: ClassVar[dict] = {"from": "field_from"} + field_from: str | None + """List of vlans as string (only one vlan if direction is "both").""" + to: int | None + """VLAN ID.""" + direction: Literal["in", "out", "both"] + """Default value: `"both"`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + field_from: str | None | UndefinedType = Undefined, + to: int | None | UndefinedType = Undefined, + direction: Literal["in", "out", "both"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VlanTranslationsItem. + + + Subclass of AvdModel. + + Args: + field_from: List of vlans as string (only one vlan if direction is "both"). + to: VLAN ID. + direction: direction + _custom_data: _custom_data + + """ + + class VlanTranslations(AvdList[VlanTranslationsItem]): + """Subclass of AvdList with `VlanTranslationsItem` items.""" + + VlanTranslations._item_type = VlanTranslationsItem + + class Shape(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"rate": {"type": str}, "_custom_data": {"type": dict}} + rate: str | None + """ + Rate in kbps, pps or percent. + Supported options are platform dependent. + Examples: + - "5000 kbps" + - + "1000 pps" + - "20 percent" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, rate: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Shape. + + + Subclass of AvdModel. + + Args: + rate: + Rate in kbps, pps or percent. + Supported options are platform dependent. + Examples: # fmt: skip + - "5000 kbps" + - + "1000 pps" + - "20 percent" + _custom_data: _custom_data + + """ + + class StormControl(AvdModel): + """Subclass of AvdModel.""" + + class All(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional field and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + All. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional field and is hardware dependent. + _custom_data: _custom_data + + """ + + class Broadcast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional field and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Broadcast. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional field and is hardware dependent. + _custom_data: _custom_data + + """ + + class Multicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional field and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Multicast. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional field and is hardware dependent. + _custom_data: _custom_data + + """ + + class UnknownUnicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional field and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + UnknownUnicast. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional field and is hardware dependent. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "all": {"type": All}, + "broadcast": {"type": Broadcast}, + "multicast": {"type": Multicast}, + "unknown_unicast": {"type": UnknownUnicast}, + "_custom_data": {"type": dict}, + } + all: All + """Subclass of AvdModel.""" + broadcast: Broadcast + """Subclass of AvdModel.""" + multicast: Multicast + """Subclass of AvdModel.""" + unknown_unicast: UnknownUnicast + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + all: All | UndefinedType = Undefined, + broadcast: Broadcast | UndefinedType = Undefined, + multicast: Multicast | UndefinedType = Undefined, + unknown_unicast: UnknownUnicast | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StormControl. + + + Subclass of AvdModel. + + Args: + all: Subclass of AvdModel. + broadcast: Subclass of AvdModel. + multicast: Subclass of AvdModel. + unknown_unicast: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class IsisAuthentication(AvdModel): + """Subclass of AvdModel.""" + + class Both(AvdModel): + """Subclass of AvdModel.""" + + class KeyIdsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "algorithm": {"type": str}, + "key_type": {"type": str}, + "key": {"type": str}, + "rfc_5310": {"type": bool}, + "_custom_data": {"type": dict}, + } + id: int + """Configure authentication key-id.""" + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + key_type: Literal["0", "7", "8a"] + """Configure authentication key type.""" + key: str + """Password string.""" + rfc_5310: bool | None + """SHA digest computation according to rfc5310.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + key_type: Literal["0", "7", "8a"] | UndefinedType = Undefined, + key: str | UndefinedType = Undefined, + rfc_5310: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + KeyIdsItem. + + + Subclass of AvdModel. + + Args: + id: Configure authentication key-id. + algorithm: algorithm + key_type: Configure authentication key type. + key: Password string. + rfc_5310: SHA digest computation according to rfc5310. + _custom_data: _custom_data + + """ + + class KeyIds(AvdIndexedList[int, KeyIdsItem]): + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + KeyIds._item_type = KeyIdsItem + + class Sha(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"key_id": {"type": int}, "_custom_data": {"type": dict}} + key_id: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, key_id: int | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Sha. + + + Subclass of AvdModel. + + Args: + key_id: key_id + _custom_data: _custom_data + + """ + + class SharedSecret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "algorithm": {"type": str}, "_custom_data": {"type": dict}} + profile: str + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SharedSecret. + + + Subclass of AvdModel. + + Args: + profile: profile + algorithm: algorithm + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "key_type": {"type": str}, + "key": {"type": str}, + "key_ids": {"type": KeyIds}, + "mode": {"type": str}, + "sha": {"type": Sha}, + "shared_secret": {"type": SharedSecret}, + "rx_disabled": {"type": bool}, + "_custom_data": {"type": dict}, + } + key_type: Literal["0", "7", "8a"] | None + """Configure authentication key type.""" + key: str | None + """Password string. `key_type` is required for this setting.""" + key_ids: KeyIds + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + mode: Literal["md5", "sha", "text", "shared-secret"] | None + """Authentication mode.""" + sha: Sha + """ + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + """ + shared_secret: SharedSecret + """ + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + """ + rx_disabled: bool | None + """Disable authentication check on the receive side.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + key_type: Literal["0", "7", "8a"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + key_ids: KeyIds | UndefinedType = Undefined, + mode: Literal["md5", "sha", "text", "shared-secret"] | None | UndefinedType = Undefined, + sha: Sha | UndefinedType = Undefined, + shared_secret: SharedSecret | UndefinedType = Undefined, + rx_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Both. + + + Subclass of AvdModel. + + Args: + key_type: Configure authentication key type. + key: Password string. `key_type` is required for this setting. + key_ids: Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`). + mode: Authentication mode. + sha: + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + shared_secret: + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + rx_disabled: Disable authentication check on the receive side. + _custom_data: _custom_data + + """ + + class Level1(AvdModel): + """Subclass of AvdModel.""" + + class KeyIdsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "algorithm": {"type": str}, + "key_type": {"type": str}, + "key": {"type": str}, + "rfc_5310": {"type": bool}, + "_custom_data": {"type": dict}, + } + id: int + """Configure authentication key-id.""" + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + key_type: Literal["0", "7", "8a"] + """Configure authentication key type.""" + key: str + """Password string.""" + rfc_5310: bool | None + """SHA digest computation according to rfc5310.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + key_type: Literal["0", "7", "8a"] | UndefinedType = Undefined, + key: str | UndefinedType = Undefined, + rfc_5310: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + KeyIdsItem. + + + Subclass of AvdModel. + + Args: + id: Configure authentication key-id. + algorithm: algorithm + key_type: Configure authentication key type. + key: Password string. + rfc_5310: SHA digest computation according to rfc5310. + _custom_data: _custom_data + + """ + + class KeyIds(AvdIndexedList[int, KeyIdsItem]): + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + KeyIds._item_type = KeyIdsItem + + class Sha(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"key_id": {"type": int}, "_custom_data": {"type": dict}} + key_id: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, key_id: int | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Sha. + + + Subclass of AvdModel. + + Args: + key_id: key_id + _custom_data: _custom_data + + """ + + class SharedSecret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "algorithm": {"type": str}, "_custom_data": {"type": dict}} + profile: str + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SharedSecret. + + + Subclass of AvdModel. + + Args: + profile: profile + algorithm: algorithm + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "key_type": {"type": str}, + "key": {"type": str}, + "key_ids": {"type": KeyIds}, + "mode": {"type": str}, + "sha": {"type": Sha}, + "shared_secret": {"type": SharedSecret}, + "rx_disabled": {"type": bool}, + "_custom_data": {"type": dict}, + } + key_type: Literal["0", "7", "8a"] | None + """Configure authentication key type.""" + key: str | None + """Password string. `key_type` is required for this setting.""" + key_ids: KeyIds + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + mode: Literal["md5", "sha", "text", "shared-secret"] | None + """Authentication mode.""" + sha: Sha + """ + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + """ + shared_secret: SharedSecret + """ + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + """ + rx_disabled: bool | None + """Disable authentication check on the receive side.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + key_type: Literal["0", "7", "8a"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + key_ids: KeyIds | UndefinedType = Undefined, + mode: Literal["md5", "sha", "text", "shared-secret"] | None | UndefinedType = Undefined, + sha: Sha | UndefinedType = Undefined, + shared_secret: SharedSecret | UndefinedType = Undefined, + rx_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Level1. + + + Subclass of AvdModel. + + Args: + key_type: Configure authentication key type. + key: Password string. `key_type` is required for this setting. + key_ids: Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`). + mode: Authentication mode. + sha: + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + shared_secret: + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + rx_disabled: Disable authentication check on the receive side. + _custom_data: _custom_data + + """ + + class Level2(AvdModel): + """Subclass of AvdModel.""" + + class KeyIdsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "algorithm": {"type": str}, + "key_type": {"type": str}, + "key": {"type": str}, + "rfc_5310": {"type": bool}, + "_custom_data": {"type": dict}, + } + id: int + """Configure authentication key-id.""" + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + key_type: Literal["0", "7", "8a"] + """Configure authentication key type.""" + key: str + """Password string.""" + rfc_5310: bool | None + """SHA digest computation according to rfc5310.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + key_type: Literal["0", "7", "8a"] | UndefinedType = Undefined, + key: str | UndefinedType = Undefined, + rfc_5310: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + KeyIdsItem. + + + Subclass of AvdModel. + + Args: + id: Configure authentication key-id. + algorithm: algorithm + key_type: Configure authentication key type. + key: Password string. + rfc_5310: SHA digest computation according to rfc5310. + _custom_data: _custom_data + + """ + + class KeyIds(AvdIndexedList[int, KeyIdsItem]): + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + KeyIds._item_type = KeyIdsItem + + class Sha(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"key_id": {"type": int}, "_custom_data": {"type": dict}} + key_id: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, key_id: int | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Sha. + + + Subclass of AvdModel. + + Args: + key_id: key_id + _custom_data: _custom_data + + """ + + class SharedSecret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "algorithm": {"type": str}, "_custom_data": {"type": dict}} + profile: str + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SharedSecret. + + + Subclass of AvdModel. + + Args: + profile: profile + algorithm: algorithm + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "key_type": {"type": str}, + "key": {"type": str}, + "key_ids": {"type": KeyIds}, + "mode": {"type": str}, + "sha": {"type": Sha}, + "shared_secret": {"type": SharedSecret}, + "rx_disabled": {"type": bool}, + "_custom_data": {"type": dict}, + } + key_type: Literal["0", "7", "8a"] | None + """Configure authentication key type.""" + key: str | None + """Password string. `key_type` is required for this setting.""" + key_ids: KeyIds + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + mode: Literal["md5", "sha", "text", "shared-secret"] | None + """Authentication mode.""" + sha: Sha + """ + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + """ + shared_secret: SharedSecret + """ + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + """ + rx_disabled: bool | None + """Disable authentication check on the receive side.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + key_type: Literal["0", "7", "8a"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + key_ids: KeyIds | UndefinedType = Undefined, + mode: Literal["md5", "sha", "text", "shared-secret"] | None | UndefinedType = Undefined, + sha: Sha | UndefinedType = Undefined, + shared_secret: SharedSecret | UndefinedType = Undefined, + rx_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Level2. + + + Subclass of AvdModel. + + Args: + key_type: Configure authentication key type. + key: Password string. `key_type` is required for this setting. + key_ids: Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`). + mode: Authentication mode. + sha: + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + shared_secret: + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + rx_disabled: Disable authentication check on the receive side. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"both": {"type": Both}, "level_1": {"type": Level1}, "level_2": {"type": Level2}, "_custom_data": {"type": dict}} + both: Both + """ + Authentication settings for level-1 and level-2. 'both' takes precedence over 'level_1' and + 'level_2' settings. + + Subclass of AvdModel. + """ + level_1: Level1 + """ + Authentication settings for level-1. 'both' takes precedence over 'level_1' and 'level_2' settings. + Subclass of AvdModel. + """ + level_2: Level2 + """ + Authentication settings for level-2. 'both' takes precedence over 'level_1' and 'level_2' settings. + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + both: Both | UndefinedType = Undefined, + level_1: Level1 | UndefinedType = Undefined, + level_2: Level2 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IsisAuthentication. + + + Subclass of AvdModel. + + Args: + both: + Authentication settings for level-1 and level-2. 'both' takes precedence over 'level_1' and + 'level_2' settings. + + Subclass of AvdModel. + level_1: + Authentication settings for level-1. 'both' takes precedence over 'level_1' and 'level_2' settings. + Subclass of AvdModel. + level_2: + Authentication settings for level-2. 'both' takes precedence over 'level_1' and 'level_2' settings. + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class TrafficPolicy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"input": {"type": str}, "output": {"type": str}, "_custom_data": {"type": dict}} + input: str | None + """Ingress traffic policy.""" + output: str | None + """Egress traffic policy.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + input: str | None | UndefinedType = Undefined, + output: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TrafficPolicy. + + + Subclass of AvdModel. + + Args: + input: Ingress traffic policy. + output: Egress traffic policy. + _custom_data: _custom_data + + """ + + class EvpnEthernetSegment(AvdModel): + """Subclass of AvdModel.""" + + class DesignatedForwarderElection(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "algorithm": {"type": str}, + "preference_value": {"type": int}, + "dont_preempt": {"type": bool, "default": False}, + "hold_time": {"type": int}, + "subsequent_hold_time": {"type": int}, + "candidate_reachability_required": {"type": bool}, + "_custom_data": {"type": dict}, + } + algorithm: Literal["modulus", "preference"] | None + preference_value: int | None + """Preference_value is only used when "algorithm" is "preference".""" + dont_preempt: bool + """ + Dont_preempt is only used when "algorithm" is "preference". + + Default value: `False` + """ + hold_time: int | None + subsequent_hold_time: int | None + candidate_reachability_required: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + algorithm: Literal["modulus", "preference"] | None | UndefinedType = Undefined, + preference_value: int | None | UndefinedType = Undefined, + dont_preempt: bool | UndefinedType = Undefined, + hold_time: int | None | UndefinedType = Undefined, + subsequent_hold_time: int | None | UndefinedType = Undefined, + candidate_reachability_required: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DesignatedForwarderElection. + + + Subclass of AvdModel. + + Args: + algorithm: algorithm + preference_value: Preference_value is only used when "algorithm" is "preference". + dont_preempt: Dont_preempt is only used when "algorithm" is "preference". + hold_time: hold_time + subsequent_hold_time: subsequent_hold_time + candidate_reachability_required: candidate_reachability_required + _custom_data: _custom_data + + """ + + class Mpls(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"shared_index": {"type": int}, "tunnel_flood_filter_time": {"type": int}, "_custom_data": {"type": dict}} + shared_index: int | None + tunnel_flood_filter_time: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + shared_index: int | None | UndefinedType = Undefined, + tunnel_flood_filter_time: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Mpls. + + + Subclass of AvdModel. + + Args: + shared_index: shared_index + tunnel_flood_filter_time: tunnel_flood_filter_time + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "identifier": {"type": str}, + "redundancy": {"type": str}, + "designated_forwarder_election": {"type": DesignatedForwarderElection}, + "mpls": {"type": Mpls}, + "route_target": {"type": str}, + "_custom_data": {"type": dict}, + } + identifier: str | None + """EVPN Ethernet Segment Identifier (Type 1 format).""" + redundancy: Literal["all-active", "single-active"] | None + designated_forwarder_election: DesignatedForwarderElection + """Subclass of AvdModel.""" + mpls: Mpls + """Subclass of AvdModel.""" + route_target: str | None + """EVPN Route Target for ESI with format xx:xx:xx:xx:xx:xx.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + identifier: str | None | UndefinedType = Undefined, + redundancy: Literal["all-active", "single-active"] | None | UndefinedType = Undefined, + designated_forwarder_election: DesignatedForwarderElection | UndefinedType = Undefined, + mpls: Mpls | UndefinedType = Undefined, + route_target: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnEthernetSegment. + + + Subclass of AvdModel. + + Args: + identifier: EVPN Ethernet Segment Identifier (Type 1 format). + redundancy: redundancy + designated_forwarder_election: Subclass of AvdModel. + mpls: Subclass of AvdModel. + route_target: EVPN Route Target for ESI with format xx:xx:xx:xx:xx:xx. + _custom_data: _custom_data + + """ + + class Ptp(AvdModel): + """Subclass of AvdModel.""" + + class Announce(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interval": {"type": int}, "timeout": {"type": int}, "_custom_data": {"type": dict}} + interval: int | None + timeout: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | None | UndefinedType = Undefined, + timeout: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Announce. + + + Subclass of AvdModel. + + Args: + interval: interval + timeout: timeout + _custom_data: _custom_data + + """ + + class Profile(AvdModel): + """Subclass of AvdModel.""" + + class G82751(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"destination_mac_address": {"type": str}, "_custom_data": {"type": dict}} + destination_mac_address: Literal["forwardable", "non-forwardable"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + destination_mac_address: Literal["forwardable", "non-forwardable"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + G82751. + + + Subclass of AvdModel. + + Args: + destination_mac_address: destination_mac_address + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"g8275_1": {"type": G82751}, "_custom_data": {"type": dict}} + g8275_1: G82751 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, g8275_1: G82751 | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Profile. + + + Subclass of AvdModel. + + Args: + g8275_1: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class SyncMessage(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interval": {"type": int}, "_custom_data": {"type": dict}} + interval: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, interval: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + SyncMessage. + + + Subclass of AvdModel. + + Args: + interval: interval + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enable": {"type": bool}, + "announce": {"type": Announce}, + "delay_req": {"type": int}, + "delay_mechanism": {"type": str}, + "profile": {"type": Profile}, + "sync_message": {"type": SyncMessage}, + "role": {"type": str}, + "vlan": {"type": str}, + "transport": {"type": str}, + "mpass": {"type": bool}, + "_custom_data": {"type": dict}, + } + enable: bool | None + announce: Announce + """Subclass of AvdModel.""" + delay_req: int | None + delay_mechanism: Literal["e2e", "p2p"] | None + profile: Profile + """Subclass of AvdModel.""" + sync_message: SyncMessage + """Subclass of AvdModel.""" + role: Literal["master", "dynamic"] | None + vlan: str | None + """VLAN can be 'all' or list of vlans as string.""" + transport: Literal["ipv4", "ipv6", "layer2"] | None + mpass: bool | None + """ + When MPASS is enabled on an MLAG port-channel, MLAG peers coordinate to function as a single PTP + logical device. + Arista PTP enabled devices always place PTP messages on the same physical link + within the port-channel. + Hence, MPASS is needed only on MLAG port-channels connected to non-Arista + devices. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enable: bool | None | UndefinedType = Undefined, + announce: Announce | UndefinedType = Undefined, + delay_req: int | None | UndefinedType = Undefined, + delay_mechanism: Literal["e2e", "p2p"] | None | UndefinedType = Undefined, + profile: Profile | UndefinedType = Undefined, + sync_message: SyncMessage | UndefinedType = Undefined, + role: Literal["master", "dynamic"] | None | UndefinedType = Undefined, + vlan: str | None | UndefinedType = Undefined, + transport: Literal["ipv4", "ipv6", "layer2"] | None | UndefinedType = Undefined, + mpass: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ptp. + + + Subclass of AvdModel. + + Args: + enable: enable + announce: Subclass of AvdModel. + delay_req: delay_req + delay_mechanism: delay_mechanism + profile: Subclass of AvdModel. + sync_message: Subclass of AvdModel. + role: role + vlan: VLAN can be 'all' or list of vlans as string. + transport: transport + mpass: + When MPASS is enabled on an MLAG port-channel, MLAG peers coordinate to function as a single PTP + logical device. + Arista PTP enabled devices always place PTP messages on the same physical link + within the port-channel. + Hence, MPASS is needed only on MLAG port-channels connected to non-Arista + devices. + _custom_data: _custom_data + + """ + + class IpNat(AvdModel): + """Subclass of AvdModel.""" + + class Destination(AvdModel): + """Subclass of AvdModel.""" + + class DynamicItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "access_list": {"type": str}, + "comment": {"type": str}, + "pool_name": {"type": str}, + "priority": {"type": int}, + "_custom_data": {"type": dict}, + } + access_list: str + comment: str | None + pool_name: str + priority: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + access_list: str | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + pool_name: str | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DynamicItem. + + + Subclass of AvdModel. + + Args: + access_list: access_list + comment: comment + pool_name: pool_name + priority: priority + _custom_data: _custom_data + + """ + + class Dynamic(AvdIndexedList[str, DynamicItem]): + """Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`).""" + + _primary_key: ClassVar[str] = "access_list" + + Dynamic._item_type = DynamicItem + + class StaticItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "access_list": {"type": str}, + "comment": {"type": str}, + "direction": {"type": str}, + "group": {"type": int}, + "original_ip": {"type": str}, + "original_port": {"type": int}, + "priority": {"type": int}, + "protocol": {"type": str}, + "translated_ip": {"type": str}, + "translated_port": {"type": int}, + "_custom_data": {"type": dict}, + } + access_list: str | None + """'access_list' and 'group' are mutual exclusive.""" + comment: str | None + direction: Literal["egress", "ingress"] | None + """ + Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware + platform. + EOS might remove this keyword in the configuration. So, check the configuration on + targeted HW/SW. + """ + group: int | None + """'access_list' and 'group' are mutual exclusive.""" + original_ip: str | None + """IPv4 address. The combination of `original_ip` and `original_port` must be unique.""" + original_port: int | None + """TCP/UDP port. The combination of `original_ip` and `original_port` must be unique.""" + priority: int | None + protocol: Literal["udp", "tcp"] | None + translated_ip: str + """IPv4 address.""" + translated_port: int | None + """requires 'original_port'.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + access_list: str | None | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + direction: Literal["egress", "ingress"] | None | UndefinedType = Undefined, + group: int | None | UndefinedType = Undefined, + original_ip: str | None | UndefinedType = Undefined, + original_port: int | None | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + protocol: Literal["udp", "tcp"] | None | UndefinedType = Undefined, + translated_ip: str | UndefinedType = Undefined, + translated_port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StaticItem. + + + Subclass of AvdModel. + + Args: + access_list: 'access_list' and 'group' are mutual exclusive. + comment: comment + direction: + Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware + platform. + EOS might remove this keyword in the configuration. So, check the configuration on + targeted HW/SW. + group: 'access_list' and 'group' are mutual exclusive. + original_ip: IPv4 address. The combination of `original_ip` and `original_port` must be unique. + original_port: TCP/UDP port. The combination of `original_ip` and `original_port` must be unique. + priority: priority + protocol: protocol + translated_ip: IPv4 address. + translated_port: requires 'original_port'. + _custom_data: _custom_data + + """ + + class Static(AvdList[StaticItem]): + """Subclass of AvdList with `StaticItem` items.""" + + Static._item_type = StaticItem + + _fields: ClassVar[dict] = {"dynamic": {"type": Dynamic}, "static": {"type": Static}, "_custom_data": {"type": dict}} + dynamic: Dynamic + """Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`).""" + static: Static + """Subclass of AvdList with `StaticItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dynamic: Dynamic | UndefinedType = Undefined, + static: Static | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Destination. + + + Subclass of AvdModel. + + Args: + dynamic: Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`). + static: Subclass of AvdList with `StaticItem` items. + _custom_data: _custom_data + + """ + + class Source(AvdModel): + """Subclass of AvdModel.""" + + class DynamicItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "access_list": {"type": str}, + "comment": {"type": str}, + "nat_type": {"type": str}, + "pool_name": {"type": str}, + "priority": {"type": int}, + "_custom_data": {"type": dict}, + } + access_list: str + comment: str | None + nat_type: Literal["overload", "pool", "pool-address-only", "pool-full-cone"] + pool_name: str | None + """ + required if 'nat_type' is pool, pool-address-only or pool-full-cone. + ignored if 'nat_type' is + overload. + """ + priority: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + access_list: str | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + nat_type: Literal["overload", "pool", "pool-address-only", "pool-full-cone"] | UndefinedType = Undefined, + pool_name: str | None | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DynamicItem. + + + Subclass of AvdModel. + + Args: + access_list: access_list + comment: comment + nat_type: nat_type + pool_name: + required if 'nat_type' is pool, pool-address-only or pool-full-cone. + ignored if 'nat_type' is + overload. + priority: priority + _custom_data: _custom_data + + """ + + class Dynamic(AvdIndexedList[str, DynamicItem]): + """Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`).""" + + _primary_key: ClassVar[str] = "access_list" + + Dynamic._item_type = DynamicItem + + class StaticItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "access_list": {"type": str}, + "comment": {"type": str}, + "direction": {"type": str}, + "group": {"type": int}, + "original_ip": {"type": str}, + "original_port": {"type": int}, + "priority": {"type": int}, + "protocol": {"type": str}, + "translated_ip": {"type": str}, + "translated_port": {"type": int}, + "_custom_data": {"type": dict}, + } + access_list: str | None + """'access_list' and 'group' are mutual exclusive.""" + comment: str | None + direction: Literal["egress", "ingress"] | None + """ + Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware + platform. + EOS might remove this keyword in the configuration. So, check the configuration on + targeted HW/SW. + """ + group: int | None + """'access_list' and 'group' are mutual exclusive.""" + original_ip: str | None + """IPv4 address. The combination of `original_ip` and `original_port` must be unique.""" + original_port: int | None + """TCP/UDP port. The combination of `original_ip` and `original_port` must be unique.""" + priority: int | None + protocol: Literal["udp", "tcp"] | None + translated_ip: str + """IPv4 address.""" + translated_port: int | None + """requires 'original_port'.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + access_list: str | None | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + direction: Literal["egress", "ingress"] | None | UndefinedType = Undefined, + group: int | None | UndefinedType = Undefined, + original_ip: str | None | UndefinedType = Undefined, + original_port: int | None | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + protocol: Literal["udp", "tcp"] | None | UndefinedType = Undefined, + translated_ip: str | UndefinedType = Undefined, + translated_port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StaticItem. + + + Subclass of AvdModel. + + Args: + access_list: 'access_list' and 'group' are mutual exclusive. + comment: comment + direction: + Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware + platform. + EOS might remove this keyword in the configuration. So, check the configuration on + targeted HW/SW. + group: 'access_list' and 'group' are mutual exclusive. + original_ip: IPv4 address. The combination of `original_ip` and `original_port` must be unique. + original_port: TCP/UDP port. The combination of `original_ip` and `original_port` must be unique. + priority: priority + protocol: protocol + translated_ip: IPv4 address. + translated_port: requires 'original_port'. + _custom_data: _custom_data + + """ + + class Static(AvdList[StaticItem]): + """Subclass of AvdList with `StaticItem` items.""" + + Static._item_type = StaticItem + + _fields: ClassVar[dict] = {"dynamic": {"type": Dynamic}, "static": {"type": Static}, "_custom_data": {"type": dict}} + dynamic: Dynamic + """Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`).""" + static: Static + """Subclass of AvdList with `StaticItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dynamic: Dynamic | UndefinedType = Undefined, + static: Static | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Source. + + + Subclass of AvdModel. + + Args: + dynamic: Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`). + static: Subclass of AvdList with `StaticItem` items. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"destination": {"type": Destination}, "source": {"type": Source}, "_custom_data": {"type": dict}} + destination: Destination + """Subclass of AvdModel.""" + source: Source + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + destination: Destination | UndefinedType = Undefined, + source: Source | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpNat. + + + Subclass of AvdModel. + + Args: + destination: Subclass of AvdModel. + source: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Ipv6NdPrefixesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "ipv6_prefix": {"type": str}, + "valid_lifetime": {"type": str}, + "preferred_lifetime": {"type": str}, + "no_autoconfig_flag": {"type": bool}, + "_custom_data": {"type": dict}, + } + ipv6_prefix: str + valid_lifetime: str | None + """Infinite or lifetime in seconds.""" + preferred_lifetime: str | None + """Infinite or lifetime in seconds.""" + no_autoconfig_flag: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv6_prefix: str | UndefinedType = Undefined, + valid_lifetime: str | None | UndefinedType = Undefined, + preferred_lifetime: str | None | UndefinedType = Undefined, + no_autoconfig_flag: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6NdPrefixesItem. + + + Subclass of AvdModel. + + Args: + ipv6_prefix: ipv6_prefix + valid_lifetime: Infinite or lifetime in seconds. + preferred_lifetime: Infinite or lifetime in seconds. + no_autoconfig_flag: no_autoconfig_flag + _custom_data: _custom_data + + """ + + class Ipv6NdPrefixes(AvdIndexedList[str, Ipv6NdPrefixesItem]): + """Subclass of AvdIndexedList with `Ipv6NdPrefixesItem` items. Primary key is `ipv6_prefix` (`str`).""" + + _primary_key: ClassVar[str] = "ipv6_prefix" + + Ipv6NdPrefixes._item_type = Ipv6NdPrefixesItem + + class Pim(AvdModel): + """Subclass of AvdModel.""" + + class Ipv4(AvdModel): + """Subclass of AvdModel.""" + + class Hello(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"count": {"type": str}, "interval": {"type": int}, "_custom_data": {"type": dict}} + count: str | None + """Number of missed hellos after which the neighbor expires. Range <1.5-65535>.""" + interval: int | None + """PIM hello interval in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + count: str | None | UndefinedType = Undefined, + interval: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Hello. + + + Subclass of AvdModel. + + Args: + count: Number of missed hellos after which the neighbor expires. Range <1.5-65535>. + interval: PIM hello interval in seconds. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "border_router": {"type": bool}, + "dr_priority": {"type": int}, + "sparse_mode": {"type": bool}, + "bfd": {"type": bool}, + "bidirectional": {"type": bool}, + "hello": {"type": Hello}, + "_custom_data": {"type": dict}, + } + border_router: bool | None + """Configure PIM border router. EOS default is false.""" + dr_priority: int | None + sparse_mode: bool | None + bfd: bool | None + """Set the default for whether Bidirectional Forwarding Detection is enabled for PIM.""" + bidirectional: bool | None + hello: Hello + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + border_router: bool | None | UndefinedType = Undefined, + dr_priority: int | None | UndefinedType = Undefined, + sparse_mode: bool | None | UndefinedType = Undefined, + bfd: bool | None | UndefinedType = Undefined, + bidirectional: bool | None | UndefinedType = Undefined, + hello: Hello | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4. + + + Subclass of AvdModel. + + Args: + border_router: Configure PIM border router. EOS default is false. + dr_priority: dr_priority + sparse_mode: sparse_mode + bfd: Set the default for whether Bidirectional Forwarding Detection is enabled for PIM. + bidirectional: bidirectional + hello: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ipv4": {"type": Ipv4}, "_custom_data": {"type": dict}} + ipv4: Ipv4 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, ipv4: Ipv4 | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Pim. + + + Subclass of AvdModel. + + Args: + ipv4: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class OspfMessageDigestKeysItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"id": {"type": int}, "hash_algorithm": {"type": str}, "key": {"type": str}, "_custom_data": {"type": dict}} + id: int + hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None + key: str | None + """Encrypted password.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + OspfMessageDigestKeysItem. + + + Subclass of AvdModel. + + Args: + id: id + hash_algorithm: hash_algorithm + key: Encrypted password. + _custom_data: _custom_data + + """ + + class OspfMessageDigestKeys(AvdIndexedList[int, OspfMessageDigestKeysItem]): + """Subclass of AvdIndexedList with `OspfMessageDigestKeysItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + OspfMessageDigestKeys._item_type = OspfMessageDigestKeysItem + + class FlowTracker(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"sampled": {"type": str}, "hardware": {"type": str}, "_custom_data": {"type": dict}} + sampled: str | None + """Sampled flow tracker name.""" + hardware: str | None + """Hardware flow tracker name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sampled: str | None | UndefinedType = Undefined, + hardware: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracker. + + + Subclass of AvdModel. + + Args: + sampled: Sampled flow tracker name. + hardware: Hardware flow tracker name. + _custom_data: _custom_data + + """ + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"session_tracker": {"type": str}, "_custom_data": {"type": dict}} + session_tracker: str | None + """Name of session tracker.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, session_tracker: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + session_tracker: Name of session tracker. + _custom_data: _custom_data + + """ + + class IpIgmpHostProxy(AvdModel): + """Subclass of AvdModel.""" + + class GroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class ExcludeItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"source": {"type": str}, "_custom_data": {"type": dict}} + source: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, source: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + ExcludeItem. + + + Subclass of AvdModel. + + Args: + source: source + _custom_data: _custom_data + + """ + + class Exclude(AvdIndexedList[str, ExcludeItem]): + """Subclass of AvdIndexedList with `ExcludeItem` items. Primary key is `source` (`str`).""" + + _primary_key: ClassVar[str] = "source" + + Exclude._item_type = ExcludeItem + + class IncludeItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"source": {"type": str}, "_custom_data": {"type": dict}} + source: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, source: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + IncludeItem. + + + Subclass of AvdModel. + + Args: + source: source + _custom_data: _custom_data + + """ + + class Include(AvdIndexedList[str, IncludeItem]): + """Subclass of AvdIndexedList with `IncludeItem` items. Primary key is `source` (`str`).""" + + _primary_key: ClassVar[str] = "source" + + Include._item_type = IncludeItem + + _fields: ClassVar[dict] = {"group": {"type": str}, "exclude": {"type": Exclude}, "include": {"type": Include}, "_custom_data": {"type": dict}} + group: str + """Multicast Address.""" + exclude: Exclude + """ + The same source must not be present both in `exclude` and `include` list. + + Subclass of + AvdIndexedList with `ExcludeItem` items. Primary key is `source` (`str`). + """ + include: Include + """ + The same source must not be present both in `exclude` and `include` list. + + Subclass of + AvdIndexedList with `IncludeItem` items. Primary key is `source` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + group: str | UndefinedType = Undefined, + exclude: Exclude | UndefinedType = Undefined, + include: Include | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GroupsItem. + + + Subclass of AvdModel. + + Args: + group: Multicast Address. + exclude: + The same source must not be present both in `exclude` and `include` list. + + Subclass of + AvdIndexedList with `ExcludeItem` items. Primary key is `source` (`str`). + include: + The same source must not be present both in `exclude` and `include` list. + + Subclass of + AvdIndexedList with `IncludeItem` items. Primary key is `source` (`str`). + _custom_data: _custom_data + + """ + + class Groups(AvdIndexedList[str, GroupsItem]): + """Subclass of AvdIndexedList with `GroupsItem` items. Primary key is `group` (`str`).""" + + _primary_key: ClassVar[str] = "group" + + Groups._item_type = GroupsItem + + class AccessListsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "_custom_data": {"type": dict}} + name: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, name: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + AccessListsItem. + + + Subclass of AvdModel. + + Args: + name: name + _custom_data: _custom_data + + """ + + class AccessLists(AvdIndexedList[str, AccessListsItem]): + """Subclass of AvdIndexedList with `AccessListsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + AccessLists._item_type = AccessListsItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "groups": {"type": Groups}, + "report_interval": {"type": int}, + "access_lists": {"type": AccessLists}, + "version": {"type": int}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + groups: Groups + """Subclass of AvdIndexedList with `GroupsItem` items. Primary key is `group` (`str`).""" + report_interval: int | None + """Time interval between unsolicited reports.""" + access_lists: AccessLists + """ + Non-standard Access List name. + + Subclass of AvdIndexedList with `AccessListsItem` items. Primary key + is `name` (`str`). + """ + version: int | None + """IGMP version on IGMP host-proxy interface.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + report_interval: int | None | UndefinedType = Undefined, + access_lists: AccessLists | UndefinedType = Undefined, + version: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpIgmpHostProxy. + + + Subclass of AvdModel. + + Args: + enabled: enabled + groups: Subclass of AvdIndexedList with `GroupsItem` items. Primary key is `group` (`str`). + report_interval: Time interval between unsolicited reports. + access_lists: + Non-standard Access List name. + + Subclass of AvdIndexedList with `AccessListsItem` items. Primary key + is `name` (`str`). + version: IGMP version on IGMP host-proxy interface. + _custom_data: _custom_data + + """ + + class Sflow(AvdModel): + """Subclass of AvdModel.""" + + class Egress(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enable": {"type": bool}, "unmodified_enable": {"type": bool}, "_custom_data": {"type": dict}} + enable: bool | None + unmodified_enable: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enable: bool | None | UndefinedType = Undefined, + unmodified_enable: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Egress. + + + Subclass of AvdModel. + + Args: + enable: enable + unmodified_enable: unmodified_enable + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"enable": {"type": bool}, "egress": {"type": Egress}, "_custom_data": {"type": dict}} + enable: bool | None + egress: Egress + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enable: bool | None | UndefinedType = Undefined, + egress: Egress | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Sflow. + + + Subclass of AvdModel. + + Args: + enable: enable + egress: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Switchport(AvdModel): + """Subclass of AvdModel.""" + + class Trunk(AvdModel): + """Subclass of AvdModel.""" + + class Groups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Groups._item_type = str + + _fields: ClassVar[dict] = { + "allowed_vlan": {"type": str}, + "native_vlan": {"type": int}, + "native_vlan_tag": {"type": bool}, + "private_vlan_secondary": {"type": bool}, + "groups": {"type": Groups}, + "_custom_data": {"type": dict}, + } + allowed_vlan: str | None + """ + VLAN ID or range(s) of VLAN IDs (1-4094). + Warning: This should not be combined with + `port_channel_interfaces[].mode = trunk` and `port_channel_interfaces[].vlans`. + """ + native_vlan: int | None + """ + Set native VLAN when interface is in trunking mode. + Warning: This should not be combined with + `port_channel_interfaces[].native_vlan`. + """ + native_vlan_tag: bool | None + """ + If setting both native_vlan and native_vlan_tag, native_vlan_tag takes precedence. + Warning: This + should not be combined with `port_channel_interfaces[].native_vlan_tag`. + """ + private_vlan_secondary: bool | None + """ + Enable secondary VLAN mapping for a private vlan. + Warning: This should not be combined with + `port_channel_interfaces[].trunk_private_vlan_secondary`. + """ + groups: Groups + """ + Warning: This should not be combined with `port_channel_interfaces[].trunk_groups`. + + + Subclass of + AvdList with `str` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + allowed_vlan: str | None | UndefinedType = Undefined, + native_vlan: int | None | UndefinedType = Undefined, + native_vlan_tag: bool | None | UndefinedType = Undefined, + private_vlan_secondary: bool | None | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Trunk. + + + Subclass of AvdModel. + + Args: + allowed_vlan: + VLAN ID or range(s) of VLAN IDs (1-4094). + Warning: This should not be combined with + `port_channel_interfaces[].mode = trunk` and `port_channel_interfaces[].vlans`. + native_vlan: + Set native VLAN when interface is in trunking mode. + Warning: This should not be combined with + `port_channel_interfaces[].native_vlan`. + native_vlan_tag: + If setting both native_vlan and native_vlan_tag, native_vlan_tag takes precedence. + Warning: This + should not be combined with `port_channel_interfaces[].native_vlan_tag`. + private_vlan_secondary: + Enable secondary VLAN mapping for a private vlan. + Warning: This should not be combined with + `port_channel_interfaces[].trunk_private_vlan_secondary`. + groups: + Warning: This should not be combined with `port_channel_interfaces[].trunk_groups`. + + + Subclass of + AvdList with `str` items. + _custom_data: _custom_data + + """ + + class Phone(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"vlan": {"type": int}, "trunk": {"type": str}, "_custom_data": {"type": dict}} + vlan: int | None + """Warning: This should not be combined with `port_channel_interfaces[].phone.vlan`.""" + trunk: Literal["tagged", "tagged phone", "untagged", "untagged phone"] | None + """Warning: This should not be combined with `port_channel_interfaces[].phone.trunk`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + vlan: int | None | UndefinedType = Undefined, + trunk: Literal["tagged", "tagged phone", "untagged", "untagged phone"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Phone. + + + Subclass of AvdModel. + + Args: + vlan: Warning: This should not be combined with `port_channel_interfaces[].phone.vlan`. + trunk: Warning: This should not be combined with `port_channel_interfaces[].phone.trunk` + _custom_data: _custom_data + + """ + + class Dot1q(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ethertype": {"type": int}, "vlan_tag": {"type": str}, "_custom_data": {"type": dict}} + ethertype: int | None + """Ethertype/TPID (Tag Protocol IDentifier) for VLAN tagged frames.""" + vlan_tag: Literal["disallowed", "required"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ethertype: int | None | UndefinedType = Undefined, + vlan_tag: Literal["disallowed", "required"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dot1q. + + + Subclass of AvdModel. + + Args: + ethertype: Ethertype/TPID (Tag Protocol IDentifier) for VLAN tagged frames. + vlan_tag: vlan_tag + _custom_data: _custom_data + + """ + + class VlanTranslations(AvdModel): + """Subclass of AvdModel.""" + + class DirectionInItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "field_from": {"type": str}, + "to": {"type": int}, + "dot1q_tunnel": {"type": bool}, + "inner_vlan_from": {"type": int}, + "_custom_data": {"type": dict}, + } + _field_to_key_map: ClassVar[dict] = {"field_from": "from"} + _key_to_field_map: ClassVar[dict] = {"from": "field_from"} + field_from: str | None + """VLAN ID or range of VLAN IDs to map from. Range 1-4094.""" + to: int | None + """VLAN ID to map to.""" + dot1q_tunnel: bool | None + inner_vlan_from: int | None + """Inner VLAN ID to map from.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + field_from: str | None | UndefinedType = Undefined, + to: int | None | UndefinedType = Undefined, + dot1q_tunnel: bool | None | UndefinedType = Undefined, + inner_vlan_from: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionInItem. + + + Subclass of AvdModel. + + Args: + field_from: VLAN ID or range of VLAN IDs to map from. Range 1-4094. + to: VLAN ID to map to. + dot1q_tunnel: dot1q_tunnel + inner_vlan_from: Inner VLAN ID to map from. + _custom_data: _custom_data + + """ + + class DirectionIn(AvdList[DirectionInItem]): + """Subclass of AvdList with `DirectionInItem` items.""" + + DirectionIn._item_type = DirectionInItem + + class DirectionOutItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "field_from": {"type": str}, + "to": {"type": int}, + "dot1q_tunnel_to": {"type": str}, + "inner_vlan_to": {"type": int}, + "_custom_data": {"type": dict}, + } + _field_to_key_map: ClassVar[dict] = {"field_from": "from"} + _key_to_field_map: ClassVar[dict] = {"from": "field_from"} + field_from: str + """VLAN ID or range of VLAN IDs to map from. Range 1-4094.""" + to: int | None + """VLAN ID to map to.""" + dot1q_tunnel_to: str | None + """ + VLAN ID or range of VLAN IDs or "all". Range 1-4094. + This takes precedence over `to` and + `inner_vlan_to`. + """ + inner_vlan_to: int | None + """Inner VLAN ID to map to.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + field_from: str | UndefinedType = Undefined, + to: int | None | UndefinedType = Undefined, + dot1q_tunnel_to: str | None | UndefinedType = Undefined, + inner_vlan_to: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionOutItem. + + + Subclass of AvdModel. + + Args: + field_from: VLAN ID or range of VLAN IDs to map from. Range 1-4094. + to: VLAN ID to map to. + dot1q_tunnel_to: + VLAN ID or range of VLAN IDs or "all". Range 1-4094. + This takes precedence over `to` and + `inner_vlan_to`. + inner_vlan_to: Inner VLAN ID to map to. + _custom_data: _custom_data + + """ + + class DirectionOut(AvdList[DirectionOutItem]): + """Subclass of AvdList with `DirectionOutItem` items.""" + + DirectionOut._item_type = DirectionOutItem + + class DirectionBothItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "field_from": {"type": str}, + "to": {"type": int}, + "dot1q_tunnel": {"type": bool}, + "inner_vlan_from": {"type": int}, + "network": {"type": bool}, + "_custom_data": {"type": dict}, + } + _field_to_key_map: ClassVar[dict] = {"field_from": "from"} + _key_to_field_map: ClassVar[dict] = {"from": "field_from"} + field_from: str + """VLAN ID or range of VLAN IDs to map from. Range 1-4094.""" + to: int + """VLAN ID to map to.""" + dot1q_tunnel: bool | None + inner_vlan_from: int | None + """Inner VLAN ID to map from.""" + network: bool | None + """ + Enable use of network-side VLAN ID. + This setting can only be enabled when `inner_vlan_from` is + defined. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + field_from: str | UndefinedType = Undefined, + to: int | UndefinedType = Undefined, + dot1q_tunnel: bool | None | UndefinedType = Undefined, + inner_vlan_from: int | None | UndefinedType = Undefined, + network: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionBothItem. + + + Subclass of AvdModel. + + Args: + field_from: VLAN ID or range of VLAN IDs to map from. Range 1-4094. + to: VLAN ID to map to. + dot1q_tunnel: dot1q_tunnel + inner_vlan_from: Inner VLAN ID to map from. + network: + Enable use of network-side VLAN ID. + This setting can only be enabled when `inner_vlan_from` is + defined. + _custom_data: _custom_data + + """ + + class DirectionBoth(AvdList[DirectionBothItem]): + """Subclass of AvdList with `DirectionBothItem` items.""" + + DirectionBoth._item_type = DirectionBothItem + + _fields: ClassVar[dict] = { + "in_required": {"type": bool}, + "out_required": {"type": bool}, + "direction_in": {"type": DirectionIn}, + "direction_out": {"type": DirectionOut}, + "direction_both": {"type": DirectionBoth}, + "_custom_data": {"type": dict}, + } + in_required: bool | None + """Drop the ingress traffic that do not match any VLAN mapping.""" + out_required: bool | None + """Drop the egress traffic that do not match any VLAN mapping.""" + direction_in: DirectionIn + """ + Map ingress traffic only. + + Subclass of AvdList with `DirectionInItem` items. + """ + direction_out: DirectionOut + """ + Map egress traffic only. + + Subclass of AvdList with `DirectionOutItem` items. + """ + direction_both: DirectionBoth + """ + Map both egress and ingress traffic. + + Subclass of AvdList with `DirectionBothItem` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + in_required: bool | None | UndefinedType = Undefined, + out_required: bool | None | UndefinedType = Undefined, + direction_in: DirectionIn | UndefinedType = Undefined, + direction_out: DirectionOut | UndefinedType = Undefined, + direction_both: DirectionBoth | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VlanTranslations. + + + Subclass of AvdModel. + + Args: + in_required: Drop the ingress traffic that do not match any VLAN mapping. + out_required: Drop the egress traffic that do not match any VLAN mapping. + direction_in: + Map ingress traffic only. + + Subclass of AvdList with `DirectionInItem` items. + direction_out: + Map egress traffic only. + + Subclass of AvdList with `DirectionOutItem` items. + direction_both: + Map both egress and ingress traffic. + + Subclass of AvdList with `DirectionBothItem` items. + _custom_data: _custom_data + + """ + + class BackupLink(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interface": {"type": str}, "prefer_vlan": {"type": str}, "_custom_data": {"type": dict}} + interface: str + """Backup interface. Example - Ethernet4, Vlan10 etc.""" + prefer_vlan: str | None + """VLANs to carry on the backup interface (1-4094).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interface: str | UndefinedType = Undefined, + prefer_vlan: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BackupLink. + + + Subclass of AvdModel. + + Args: + interface: Backup interface. Example - Ethernet4, Vlan10 etc. + prefer_vlan: VLANs to carry on the backup interface (1-4094). + _custom_data: _custom_data + + """ + + class Backup(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "dest_macaddr": {"type": str}, + "initial_mac_move_delay": {"type": int}, + "mac_move_burst": {"type": int}, + "mac_move_burst_interval": {"type": int}, + "preemption_delay": {"type": int}, + "_custom_data": {"type": dict}, + } + dest_macaddr: str | None + """ + Destination MAC address for MAC move updates. + The mac address should be multicast or broadcast. + Example: 01:00:00:00:00:00 + """ + initial_mac_move_delay: int | None + """Initial MAC move delay in milliseconds.""" + mac_move_burst: int | None + """Size of MAC move bursts.""" + mac_move_burst_interval: int | None + """MAC move burst interval in milliseconds.""" + preemption_delay: int | None + """Preemption delay in milliseconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dest_macaddr: str | None | UndefinedType = Undefined, + initial_mac_move_delay: int | None | UndefinedType = Undefined, + mac_move_burst: int | None | UndefinedType = Undefined, + mac_move_burst_interval: int | None | UndefinedType = Undefined, + preemption_delay: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Backup. + + + Subclass of AvdModel. + + Args: + dest_macaddr: + Destination MAC address for MAC move updates. + The mac address should be multicast or broadcast. + Example: 01:00:00:00:00:00 + initial_mac_move_delay: Initial MAC move delay in milliseconds. + mac_move_burst: Size of MAC move bursts. + mac_move_burst_interval: MAC move burst interval in milliseconds. + preemption_delay: Preemption delay in milliseconds. + _custom_data: _custom_data + + """ + + class PortSecurity(AvdModel): + """Subclass of AvdModel.""" + + class MacAddressMaximum(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"disabled": {"type": bool}, "limit": {"type": int}, "_custom_data": {"type": dict}} + disabled: bool | None + """Disable port level check for port security (only in violation 'shutdown' mode).""" + limit: int | None + """MAC address limit.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + disabled: bool | None | UndefinedType = Undefined, + limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MacAddressMaximum. + + + Subclass of AvdModel. + + Args: + disabled: Disable port level check for port security (only in violation 'shutdown' mode). + limit: MAC address limit. + _custom_data: _custom_data + + """ + + class Violation(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"mode": {"type": str}, "protect_log": {"type": bool}, "_custom_data": {"type": dict}} + mode: Literal["shutdown", "protect"] | None + """Configure port security mode.""" + protect_log: bool | None + """Log new addresses seen after limit is reached in protect mode.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["shutdown", "protect"] | None | UndefinedType = Undefined, + protect_log: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Violation. + + + Subclass of AvdModel. + + Args: + mode: Configure port security mode. + protect_log: Log new addresses seen after limit is reached in protect mode. + _custom_data: _custom_data + + """ + + class VlansItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"range": {"type": str}, "mac_address_maximum": {"type": int}, "_custom_data": {"type": dict}} + range: str + """ + VLAN ID or range(s) of VLAN IDs, <1-4094>. + Example: + - 3 + - 1,3 + - 1-10 + """ + mac_address_maximum: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + range: str | UndefinedType = Undefined, + mac_address_maximum: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VlansItem. + + + Subclass of AvdModel. + + Args: + range: + VLAN ID or range(s) of VLAN IDs, <1-4094>. + Example: # fmt: skip + - 3 + - 1,3 + - 1-10 + mac_address_maximum: mac_address_maximum + _custom_data: _custom_data + + """ + + class Vlans(AvdIndexedList[str, VlansItem]): + """Subclass of AvdIndexedList with `VlansItem` items. Primary key is `range` (`str`).""" + + _primary_key: ClassVar[str] = "range" + + Vlans._item_type = VlansItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "mac_address_maximum": {"type": MacAddressMaximum}, + "violation": {"type": Violation}, + "vlan_default_mac_address_maximum": {"type": int}, + "vlans": {"type": Vlans}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + mac_address_maximum: MacAddressMaximum + """ + Maximum number of MAC addresses allowed on the interface. + + Subclass of AvdModel. + """ + violation: Violation + """ + Configure violation mode (shutdown or protect), EOS default is 'shutdown'. + + Subclass of AvdModel. + """ + vlan_default_mac_address_maximum: int | None + """Default maximum MAC addresses for all VLANs on this interface.""" + vlans: Vlans + """Subclass of AvdIndexedList with `VlansItem` items. Primary key is `range` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + mac_address_maximum: MacAddressMaximum | UndefinedType = Undefined, + violation: Violation | UndefinedType = Undefined, + vlan_default_mac_address_maximum: int | None | UndefinedType = Undefined, + vlans: Vlans | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PortSecurity. + + + Subclass of AvdModel. + + Args: + enabled: enabled + mac_address_maximum: + Maximum number of MAC addresses allowed on the interface. + + Subclass of AvdModel. + violation: + Configure violation mode (shutdown or protect), EOS default is 'shutdown'. + + Subclass of AvdModel. + vlan_default_mac_address_maximum: Default maximum MAC addresses for all VLANs on this interface. + vlans: Subclass of AvdIndexedList with `VlansItem` items. Primary key is `range` (`str`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "mode": {"type": str}, + "access_vlan": {"type": int}, + "trunk": {"type": Trunk}, + "phone": {"type": Phone}, + "pvlan_mapping": {"type": str}, + "dot1q": {"type": Dot1q}, + "source_interface": {"type": str}, + "vlan_translations": {"type": VlanTranslations}, + "vlan_forwarding_accept_all": {"type": bool}, + "backup_link": {"type": BackupLink}, + "backup": {"type": Backup}, + "port_security": {"type": PortSecurity}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Warning: This should not be combined with `port_channel_interfaces[].type = routed`.""" + mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None + """Warning: This should not be combined with `port_channel_interfaces[].mode`""" + access_vlan: int | None + """ + Set VLAN when interface is in access mode. + Warning: This should not be combined with + `port_channel_interfaces[].mode = access/dot1q-tunnel` and `port_channel_interface.vlans`. + """ + trunk: Trunk + """Subclass of AvdModel.""" + phone: Phone + """Subclass of AvdModel.""" + pvlan_mapping: str | None + """ + Secondary VLAN IDs of the private VLAN mapping. + Warning: This should not be combined with + `port_channel_interfaces[].pvlan_mapping`. + """ + dot1q: Dot1q + """Subclass of AvdModel.""" + source_interface: Literal["tx", "tx multicast"] | None + """ + tx: Allow bridged traffic to go out of the source interface. + tx multicast: Allow multicast traffic + only to go out of the source interface. + """ + vlan_translations: VlanTranslations + """ + VLAN Translation mappings. + Warning: This should not be combined with + `port_channel_interfaces[].vlan_translations`. + + Subclass of AvdModel. + """ + vlan_forwarding_accept_all: bool | None + backup_link: BackupLink + """Subclass of AvdModel.""" + backup: Backup + """ + The `backup_link` is required for this setting. + + Subclass of AvdModel. + """ + port_security: PortSecurity + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None | UndefinedType = Undefined, + access_vlan: int | None | UndefinedType = Undefined, + trunk: Trunk | UndefinedType = Undefined, + phone: Phone | UndefinedType = Undefined, + pvlan_mapping: str | None | UndefinedType = Undefined, + dot1q: Dot1q | UndefinedType = Undefined, + source_interface: Literal["tx", "tx multicast"] | None | UndefinedType = Undefined, + vlan_translations: VlanTranslations | UndefinedType = Undefined, + vlan_forwarding_accept_all: bool | None | UndefinedType = Undefined, + backup_link: BackupLink | UndefinedType = Undefined, + backup: Backup | UndefinedType = Undefined, + port_security: PortSecurity | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Switchport. + + + Subclass of AvdModel. + + Args: + enabled: Warning: This should not be combined with `port_channel_interfaces[].type = routed`. + mode: Warning: This should not be combined with `port_channel_interfaces[].mode` + access_vlan: + Set VLAN when interface is in access mode. + Warning: This should not be combined with + `port_channel_interfaces[].mode = access/dot1q-tunnel` and `port_channel_interface.vlans`. + trunk: Subclass of AvdModel. + phone: Subclass of AvdModel. + pvlan_mapping: + Secondary VLAN IDs of the private VLAN mapping. + Warning: This should not be combined with + `port_channel_interfaces[].pvlan_mapping`. + dot1q: Subclass of AvdModel. + source_interface: + tx: Allow bridged traffic to go out of the source interface. + tx multicast: Allow multicast traffic + only to go out of the source interface. + vlan_translations: + VLAN Translation mappings. + Warning: This should not be combined with + `port_channel_interfaces[].vlan_translations`. + + Subclass of AvdModel. + vlan_forwarding_accept_all: vlan_forwarding_accept_all + backup_link: Subclass of AvdModel. + backup: + The `backup_link` is required for this setting. + + Subclass of AvdModel. + port_security: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "description": {"type": str}, + "profile": {"type": str}, + "logging": {"type": Logging}, + "shutdown": {"type": bool}, + "l2_mtu": {"type": int}, + "l2_mru": {"type": int}, + "vlans": {"type": str}, + "snmp_trap_link_change": {"type": bool}, + "type": {"type": str}, + "encapsulation_dot1q_vlan": {"type": int}, + "encapsulation_dot1q": {"type": EncapsulationDot1q}, + "vrf": {"type": str}, + "encapsulation_vlan": {"type": EncapsulationVlan}, + "vlan_id": {"type": int}, + "mode": {"type": str}, + "native_vlan": {"type": int}, + "native_vlan_tag": {"type": bool}, + "link_tracking_groups": {"type": LinkTrackingGroups}, + "link_tracking": {"type": LinkTracking}, + "phone": {"type": Phone}, + "l2_protocol": {"type": L2Protocol}, + "mtu": {"type": int}, + "mlag": {"type": int}, + "trunk_groups": {"type": TrunkGroups}, + "lacp_fallback_timeout": {"type": int}, + "lacp_fallback_mode": {"type": str}, + "qos": {"type": Qos}, + "bfd": {"type": Bfd}, + "service_policy": {"type": ServicePolicy}, + "mpls": {"type": Mpls}, + "trunk_private_vlan_secondary": {"type": bool}, + "pvlan_mapping": {"type": str}, + "vlan_translations": {"type": VlanTranslations}, + "shape": {"type": Shape}, + "storm_control": {"type": StormControl}, + "ip_proxy_arp": {"type": bool}, + "isis_enable": {"type": str}, + "isis_bfd": {"type": bool}, + "isis_passive": {"type": bool}, + "isis_metric": {"type": int}, + "isis_network_point_to_point": {"type": bool}, + "isis_circuit_type": {"type": str}, + "isis_hello_padding": {"type": bool}, + "isis_authentication_mode": {"type": str}, + "isis_authentication_key": {"type": str}, + "isis_authentication": {"type": IsisAuthentication}, + "traffic_policy": {"type": TrafficPolicy}, + "evpn_ethernet_segment": {"type": EvpnEthernetSegment}, + "lacp_id": {"type": str}, + "spanning_tree_bpdufilter": {"type": str}, + "spanning_tree_bpduguard": {"type": str}, + "spanning_tree_guard": {"type": str}, + "spanning_tree_portfast": {"type": str}, + "vmtracer": {"type": bool}, + "ptp": {"type": Ptp}, + "ip_address": {"type": str}, + "ip_verify_unicast_source_reachable_via": {"type": str}, + "ip_nat": {"type": IpNat}, + "ipv6_enable": {"type": bool}, + "ipv6_address": {"type": str}, + "ipv6_address_link_local": {"type": str}, + "ipv6_nd_ra_disabled": {"type": bool}, + "ipv6_nd_managed_config_flag": {"type": bool}, + "ipv6_nd_prefixes": {"type": Ipv6NdPrefixes}, + "access_group_in": {"type": str}, + "access_group_out": {"type": str}, + "ipv6_access_group_in": {"type": str}, + "ipv6_access_group_out": {"type": str}, + "mac_access_group_in": {"type": str}, + "mac_access_group_out": {"type": str}, + "pim": {"type": Pim}, + "service_profile": {"type": str}, + "ospf_network_point_to_point": {"type": bool}, + "ospf_area": {"type": str}, + "ospf_cost": {"type": int}, + "ospf_authentication": {"type": str}, + "ospf_authentication_key": {"type": str}, + "ospf_message_digest_keys": {"type": OspfMessageDigestKeys}, + "flow_tracker": {"type": FlowTracker}, + "bgp": {"type": Bgp}, + "ip_igmp_host_proxy": {"type": IpIgmpHostProxy}, + "peer": {"type": str}, + "peer_interface": {"type": str}, + "peer_type": {"type": str}, + "sflow": {"type": Sflow}, + "switchport": {"type": Switchport}, + "validate_state": {"type": bool}, + "validate_lldp": {"type": bool}, + "eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + description: str | None + profile: str | None + """Interface profile.""" + logging: Logging + """Subclass of AvdModel.""" + shutdown: bool | None + l2_mtu: int | None + """"l2_mtu" should only be defined for platforms supporting the "l2 mtu" CLI.""" + l2_mru: int | None + """"l2_mru" should only be defined for platforms supporting the "l2 mru" CLI.""" + vlans: str | None + """ + List of switchport vlans as string. + For a trunk port this would be a range like "1-200,300". + For an + access port this would be a single vlan "123". + """ + snmp_trap_link_change: bool | None + type: Literal["routed", "switched", "l3dot1q", "l2dot1q"] | None + """ + l3dot1q and l2dot1q are used for sub-interfaces. The parent interface should be defined as routed. + Interface will not be listed in device documentation, unless "type" is set. + """ + encapsulation_dot1q_vlan: int | None + """VLAN tag to configure on sub-interface.""" + encapsulation_dot1q: EncapsulationDot1q + """ + Warning: `encapsulation_dot1q` should not be combined with `ethernet_interfaces[].type: l3dot1q` or + `ethernet_interfaces[].type: l2dot1q`. + + Subclass of AvdModel. + """ + vrf: str | None + """VRF name.""" + encapsulation_vlan: EncapsulationVlan + """ + This setting can only be applied to sub-interfaces on EOS. + Warning: `encapsulation_vlan` should not + be combined with `ethernet_interfaces[].type: l3dot1q` or `ethernet_interfaces[].type: l2dot1q`. + Subclass of AvdModel. + """ + vlan_id: int | None + """ + This setting can only be applied to sub-interfaces on EOS. + Warning: `vlan_id` should not be combined + with `ethernet_interfaces[].type == l2dot1q`. + """ + mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None + native_vlan: int | None + """If setting both native_vlan and native_vlan_tag, native_vlan_tag takes precedence.""" + native_vlan_tag: bool | None + """If setting both native_vlan and native_vlan_tag, native_vlan_tag takes precedence.""" + link_tracking_groups: LinkTrackingGroups + """Subclass of AvdIndexedList with `LinkTrackingGroupsItem` items. Primary key is `name` (`str`).""" + link_tracking: LinkTracking + """Subclass of AvdModel.""" + phone: Phone + """Subclass of AvdModel.""" + l2_protocol: L2Protocol + """Subclass of AvdModel.""" + mtu: int | None + mlag: int | None + """MLAG ID.""" + trunk_groups: TrunkGroups + """Subclass of AvdList with `str` items.""" + lacp_fallback_timeout: int | None + """Timeout in seconds. EOS default is 90 seconds.""" + lacp_fallback_mode: Literal["individual", "static"] | None + qos: Qos + """Subclass of AvdModel.""" + bfd: Bfd + """Subclass of AvdModel.""" + service_policy: ServicePolicy + """Subclass of AvdModel.""" + mpls: Mpls + """Subclass of AvdModel.""" + trunk_private_vlan_secondary: bool | None + pvlan_mapping: str | None + """List of vlans as string.""" + vlan_translations: VlanTranslations + """Subclass of AvdList with `VlanTranslationsItem` items.""" + shape: Shape + """Subclass of AvdModel.""" + storm_control: StormControl + """Subclass of AvdModel.""" + ip_proxy_arp: bool | None + isis_enable: str | None + """ISIS instance.""" + isis_bfd: bool | None + """Enable BFD for ISIS.""" + isis_passive: bool | None + isis_metric: int | None + isis_network_point_to_point: bool | None + isis_circuit_type: Literal["level-1-2", "level-1", "level-2"] | None + isis_hello_padding: bool | None + isis_authentication_mode: Literal["text", "md5"] | None + isis_authentication_key: str | None + """Type-7 encrypted password.""" + isis_authentication: IsisAuthentication + """ + This key should not be mixed with port_channel_interfaces[].isis_authentication_mode or + ethernet_interfaces[].isis_authentication_key. + + Subclass of AvdModel. + """ + traffic_policy: TrafficPolicy + """Subclass of AvdModel.""" + evpn_ethernet_segment: EvpnEthernetSegment + """Subclass of AvdModel.""" + lacp_id: str | None + """LACP ID with format xxxx.xxxx.xxxx.""" + spanning_tree_bpdufilter: Literal["enabled", "disabled", "True", "False", "true", "false"] | None + spanning_tree_bpduguard: Literal["enabled", "disabled", "True", "False", "true", "false"] | None + spanning_tree_guard: Literal["loop", "root", "disabled"] | None + spanning_tree_portfast: Literal["edge", "network"] | None + vmtracer: bool | None + ptp: Ptp + """Subclass of AvdModel.""" + ip_address: str | None + """IPv4 address/mask.""" + ip_verify_unicast_source_reachable_via: Literal["any", "rx"] | None + ip_nat: IpNat + """Subclass of AvdModel.""" + ipv6_enable: bool | None + ipv6_address: str | None + """IPv6 address/mask.""" + ipv6_address_link_local: str | None + """Link local IPv6 address/mask.""" + ipv6_nd_ra_disabled: bool | None + ipv6_nd_managed_config_flag: bool | None + ipv6_nd_prefixes: Ipv6NdPrefixes + """Subclass of AvdIndexedList with `Ipv6NdPrefixesItem` items. Primary key is `ipv6_prefix` (`str`).""" + access_group_in: str | None + """Access list name.""" + access_group_out: str | None + """Access list name.""" + ipv6_access_group_in: str | None + """IPv6 access list name.""" + ipv6_access_group_out: str | None + """IPv6 access list name.""" + mac_access_group_in: str | None + """MAC access list name.""" + mac_access_group_out: str | None + """MAC access list name.""" + pim: Pim + """Subclass of AvdModel.""" + service_profile: str | None + """QOS profile.""" + ospf_network_point_to_point: bool | None + ospf_area: str | None + ospf_cost: int | None + ospf_authentication: Literal["none", "simple", "message-digest"] | None + ospf_authentication_key: str | None + """Encrypted password.""" + ospf_message_digest_keys: OspfMessageDigestKeys + """Subclass of AvdIndexedList with `OspfMessageDigestKeysItem` items. Primary key is `id` (`int`).""" + flow_tracker: FlowTracker + """Subclass of AvdModel.""" + bgp: Bgp + """Subclass of AvdModel.""" + ip_igmp_host_proxy: IpIgmpHostProxy + """Subclass of AvdModel.""" + peer: str | None + """Key only used for documentation or validation purposes.""" + peer_interface: str | None + """Key only used for documentation or validation purposes.""" + peer_type: str | None + """Key only used for documentation or validation purposes.""" + sflow: Sflow + """Subclass of AvdModel.""" + switchport: Switchport + """Subclass of AvdModel.""" + validate_state: bool | None + """ + Set to false to disable interface state and LLDP topology validation performed by the + `eos_validate_state` role. + """ + validate_lldp: bool | None + """Set to false to disable the LLDP topology validation performed by the `eos_validate_state` role.""" + eos_cli: str | None + """Multiline EOS CLI rendered directly on the port-channel interface in the final EOS configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + profile: str | None | UndefinedType = Undefined, + logging: Logging | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + l2_mtu: int | None | UndefinedType = Undefined, + l2_mru: int | None | UndefinedType = Undefined, + vlans: str | None | UndefinedType = Undefined, + snmp_trap_link_change: bool | None | UndefinedType = Undefined, + type: Literal["routed", "switched", "l3dot1q", "l2dot1q"] | None | UndefinedType = Undefined, + encapsulation_dot1q_vlan: int | None | UndefinedType = Undefined, + encapsulation_dot1q: EncapsulationDot1q | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + encapsulation_vlan: EncapsulationVlan | UndefinedType = Undefined, + vlan_id: int | None | UndefinedType = Undefined, + mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None | UndefinedType = Undefined, + native_vlan: int | None | UndefinedType = Undefined, + native_vlan_tag: bool | None | UndefinedType = Undefined, + link_tracking_groups: LinkTrackingGroups | UndefinedType = Undefined, + link_tracking: LinkTracking | UndefinedType = Undefined, + phone: Phone | UndefinedType = Undefined, + l2_protocol: L2Protocol | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + mlag: int | None | UndefinedType = Undefined, + trunk_groups: TrunkGroups | UndefinedType = Undefined, + lacp_fallback_timeout: int | None | UndefinedType = Undefined, + lacp_fallback_mode: Literal["individual", "static"] | None | UndefinedType = Undefined, + qos: Qos | UndefinedType = Undefined, + bfd: Bfd | UndefinedType = Undefined, + service_policy: ServicePolicy | UndefinedType = Undefined, + mpls: Mpls | UndefinedType = Undefined, + trunk_private_vlan_secondary: bool | None | UndefinedType = Undefined, + pvlan_mapping: str | None | UndefinedType = Undefined, + vlan_translations: VlanTranslations | UndefinedType = Undefined, + shape: Shape | UndefinedType = Undefined, + storm_control: StormControl | UndefinedType = Undefined, + ip_proxy_arp: bool | None | UndefinedType = Undefined, + isis_enable: str | None | UndefinedType = Undefined, + isis_bfd: bool | None | UndefinedType = Undefined, + isis_passive: bool | None | UndefinedType = Undefined, + isis_metric: int | None | UndefinedType = Undefined, + isis_network_point_to_point: bool | None | UndefinedType = Undefined, + isis_circuit_type: Literal["level-1-2", "level-1", "level-2"] | None | UndefinedType = Undefined, + isis_hello_padding: bool | None | UndefinedType = Undefined, + isis_authentication_mode: Literal["text", "md5"] | None | UndefinedType = Undefined, + isis_authentication_key: str | None | UndefinedType = Undefined, + isis_authentication: IsisAuthentication | UndefinedType = Undefined, + traffic_policy: TrafficPolicy | UndefinedType = Undefined, + evpn_ethernet_segment: EvpnEthernetSegment | UndefinedType = Undefined, + lacp_id: str | None | UndefinedType = Undefined, + spanning_tree_bpdufilter: Literal["enabled", "disabled", "True", "False", "true", "false"] | None | UndefinedType = Undefined, + spanning_tree_bpduguard: Literal["enabled", "disabled", "True", "False", "true", "false"] | None | UndefinedType = Undefined, + spanning_tree_guard: Literal["loop", "root", "disabled"] | None | UndefinedType = Undefined, + spanning_tree_portfast: Literal["edge", "network"] | None | UndefinedType = Undefined, + vmtracer: bool | None | UndefinedType = Undefined, + ptp: Ptp | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + ip_verify_unicast_source_reachable_via: Literal["any", "rx"] | None | UndefinedType = Undefined, + ip_nat: IpNat | UndefinedType = Undefined, + ipv6_enable: bool | None | UndefinedType = Undefined, + ipv6_address: str | None | UndefinedType = Undefined, + ipv6_address_link_local: str | None | UndefinedType = Undefined, + ipv6_nd_ra_disabled: bool | None | UndefinedType = Undefined, + ipv6_nd_managed_config_flag: bool | None | UndefinedType = Undefined, + ipv6_nd_prefixes: Ipv6NdPrefixes | UndefinedType = Undefined, + access_group_in: str | None | UndefinedType = Undefined, + access_group_out: str | None | UndefinedType = Undefined, + ipv6_access_group_in: str | None | UndefinedType = Undefined, + ipv6_access_group_out: str | None | UndefinedType = Undefined, + mac_access_group_in: str | None | UndefinedType = Undefined, + mac_access_group_out: str | None | UndefinedType = Undefined, + pim: Pim | UndefinedType = Undefined, + service_profile: str | None | UndefinedType = Undefined, + ospf_network_point_to_point: bool | None | UndefinedType = Undefined, + ospf_area: str | None | UndefinedType = Undefined, + ospf_cost: int | None | UndefinedType = Undefined, + ospf_authentication: Literal["none", "simple", "message-digest"] | None | UndefinedType = Undefined, + ospf_authentication_key: str | None | UndefinedType = Undefined, + ospf_message_digest_keys: OspfMessageDigestKeys | UndefinedType = Undefined, + flow_tracker: FlowTracker | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + ip_igmp_host_proxy: IpIgmpHostProxy | UndefinedType = Undefined, + peer: str | None | UndefinedType = Undefined, + peer_interface: str | None | UndefinedType = Undefined, + peer_type: str | None | UndefinedType = Undefined, + sflow: Sflow | UndefinedType = Undefined, + switchport: Switchport | UndefinedType = Undefined, + validate_state: bool | None | UndefinedType = Undefined, + validate_lldp: bool | None | UndefinedType = Undefined, + eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PortChannelInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: name + description: description + profile: Interface profile. + logging: Subclass of AvdModel. + shutdown: shutdown + l2_mtu: "l2_mtu" should only be defined for platforms supporting the "l2 mtu" CLI. + l2_mru: "l2_mru" should only be defined for platforms supporting the "l2 mru" CLI. + vlans: + List of switchport vlans as string. + For a trunk port this would be a range like "1-200,300". + For an + access port this would be a single vlan "123". + snmp_trap_link_change: snmp_trap_link_change + type: + l3dot1q and l2dot1q are used for sub-interfaces. The parent interface should be defined as routed. + Interface will not be listed in device documentation, unless "type" is set. + encapsulation_dot1q_vlan: VLAN tag to configure on sub-interface. + encapsulation_dot1q: + Warning: `encapsulation_dot1q` should not be combined with `ethernet_interfaces[].type: l3dot1q` or + `ethernet_interfaces[].type: l2dot1q`. + + Subclass of AvdModel. + vrf: VRF name. + encapsulation_vlan: + This setting can only be applied to sub-interfaces on EOS. + Warning: `encapsulation_vlan` should not + be combined with `ethernet_interfaces[].type: l3dot1q` or `ethernet_interfaces[].type: l2dot1q`. + Subclass of AvdModel. + vlan_id: + This setting can only be applied to sub-interfaces on EOS. + Warning: `vlan_id` should not be combined + with `ethernet_interfaces[].type == l2dot1q`. + mode: mode + native_vlan: If setting both native_vlan and native_vlan_tag, native_vlan_tag takes precedence. + native_vlan_tag: If setting both native_vlan and native_vlan_tag, native_vlan_tag takes precedence. + link_tracking_groups: Subclass of AvdIndexedList with `LinkTrackingGroupsItem` items. Primary key is `name` (`str`). + link_tracking: Subclass of AvdModel. + phone: Subclass of AvdModel. + l2_protocol: Subclass of AvdModel. + mtu: mtu + mlag: MLAG ID. + trunk_groups: Subclass of AvdList with `str` items. + lacp_fallback_timeout: Timeout in seconds. EOS default is 90 seconds. + lacp_fallback_mode: lacp_fallback_mode + qos: Subclass of AvdModel. + bfd: Subclass of AvdModel. + service_policy: Subclass of AvdModel. + mpls: Subclass of AvdModel. + trunk_private_vlan_secondary: trunk_private_vlan_secondary + pvlan_mapping: List of vlans as string. + vlan_translations: Subclass of AvdList with `VlanTranslationsItem` items. + shape: Subclass of AvdModel. + storm_control: Subclass of AvdModel. + ip_proxy_arp: ip_proxy_arp + isis_enable: ISIS instance. + isis_bfd: Enable BFD for ISIS. + isis_passive: isis_passive + isis_metric: isis_metric + isis_network_point_to_point: isis_network_point_to_point + isis_circuit_type: isis_circuit_type + isis_hello_padding: isis_hello_padding + isis_authentication_mode: isis_authentication_mode + isis_authentication_key: Type-7 encrypted password. + isis_authentication: + This key should not be mixed with port_channel_interfaces[].isis_authentication_mode or + ethernet_interfaces[].isis_authentication_key. + + Subclass of AvdModel. + traffic_policy: Subclass of AvdModel. + evpn_ethernet_segment: Subclass of AvdModel. + lacp_id: LACP ID with format xxxx.xxxx.xxxx. + spanning_tree_bpdufilter: spanning_tree_bpdufilter + spanning_tree_bpduguard: spanning_tree_bpduguard + spanning_tree_guard: spanning_tree_guard + spanning_tree_portfast: spanning_tree_portfast + vmtracer: vmtracer + ptp: Subclass of AvdModel. + ip_address: IPv4 address/mask. + ip_verify_unicast_source_reachable_via: ip_verify_unicast_source_reachable_via + ip_nat: Subclass of AvdModel. + ipv6_enable: ipv6_enable + ipv6_address: IPv6 address/mask. + ipv6_address_link_local: Link local IPv6 address/mask. + ipv6_nd_ra_disabled: ipv6_nd_ra_disabled + ipv6_nd_managed_config_flag: ipv6_nd_managed_config_flag + ipv6_nd_prefixes: Subclass of AvdIndexedList with `Ipv6NdPrefixesItem` items. Primary key is `ipv6_prefix` (`str`). + access_group_in: Access list name. + access_group_out: Access list name. + ipv6_access_group_in: IPv6 access list name. + ipv6_access_group_out: IPv6 access list name. + mac_access_group_in: MAC access list name. + mac_access_group_out: MAC access list name. + pim: Subclass of AvdModel. + service_profile: QOS profile. + ospf_network_point_to_point: ospf_network_point_to_point + ospf_area: ospf_area + ospf_cost: ospf_cost + ospf_authentication: ospf_authentication + ospf_authentication_key: Encrypted password. + ospf_message_digest_keys: Subclass of AvdIndexedList with `OspfMessageDigestKeysItem` items. Primary key is `id` (`int`). + flow_tracker: Subclass of AvdModel. + bgp: Subclass of AvdModel. + ip_igmp_host_proxy: Subclass of AvdModel. + peer: Key only used for documentation or validation purposes. + peer_interface: Key only used for documentation or validation purposes. + peer_type: Key only used for documentation or validation purposes. + sflow: Subclass of AvdModel. + switchport: Subclass of AvdModel. + validate_state: + Set to false to disable interface state and LLDP topology validation performed by the + `eos_validate_state` role. + validate_lldp: Set to false to disable the LLDP topology validation performed by the `eos_validate_state` role. + eos_cli: Multiline EOS CLI rendered directly on the port-channel interface in the final EOS configuration. + _custom_data: _custom_data + + """ + + class PortChannelInterfaces(AvdIndexedList[str, PortChannelInterfacesItem]): + """Subclass of AvdIndexedList with `PortChannelInterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PortChannelInterfaces._item_type = PortChannelInterfacesItem + + class PrefixListsItem(AvdModel): + """Subclass of AvdModel.""" + + class SequenceNumbersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"sequence": {"type": int}, "action": {"type": str}, "_custom_data": {"type": dict}} + sequence: int + """Sequence ID.""" + action: str + """ + Action as string. + Example: "permit 10.255.0.0/27 eq 32" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sequence: int | UndefinedType = Undefined, + action: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceNumbersItem. + + + Subclass of AvdModel. + + Args: + sequence: Sequence ID. + action: + Action as string. + Example: "permit 10.255.0.0/27 eq 32" + _custom_data: _custom_data + + """ + + class SequenceNumbers(AvdIndexedList[int, SequenceNumbersItem]): + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + + _primary_key: ClassVar[str] = "sequence" + + SequenceNumbers._item_type = SequenceNumbersItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "sequence_numbers": {"type": SequenceNumbers}, "_custom_data": {"type": dict}} + name: str + """Prefix-list Name.""" + sequence_numbers: SequenceNumbers + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + sequence_numbers: SequenceNumbers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PrefixListsItem. + + + Subclass of AvdModel. + + Args: + name: Prefix-list Name. + sequence_numbers: Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`). + _custom_data: _custom_data + + """ + + class PrefixLists(AvdIndexedList[str, PrefixListsItem]): + """Subclass of AvdIndexedList with `PrefixListsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PrefixLists._item_type = PrefixListsItem + + class PriorityFlowControl(AvdModel): + """Subclass of AvdModel.""" + + class Watchdog(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "action": {"type": str}, + "timeout": {"type": str}, + "polling_interval": {"type": str}, + "recovery_time": {"type": str}, + "override_action_drop": {"type": bool}, + "_custom_data": {"type": dict}, + } + action: Literal["drop", "no-drop"] | None + """Action on stuck queue.""" + timeout: str | None + """ + Timeout in seconds after which port should be errdisabled or + should start dropping on congested + priorities. + This should be decimal with up to 2 decimal point. + Example: 0.01 or 60 + """ + polling_interval: str | None + """ + Time interval in seconds at which the watchdog should poll the queues. + This should be decimal with + up to 3 decimal point. + Example: 0.005 or 60 + """ + recovery_time: str | None + """ + Recovery-time in seconds after which stuck queue should + recover and start forwarding again. + This + should be decimal with up to 2 decimal point. + Example: 0.01 or 60 + """ + override_action_drop: bool | None + """Override configured action on stuck queue to drop.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["drop", "no-drop"] | None | UndefinedType = Undefined, + timeout: str | None | UndefinedType = Undefined, + polling_interval: str | None | UndefinedType = Undefined, + recovery_time: str | None | UndefinedType = Undefined, + override_action_drop: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Watchdog. + + + Subclass of AvdModel. + + Args: + action: Action on stuck queue. + timeout: + Timeout in seconds after which port should be errdisabled or + should start dropping on congested + priorities. + This should be decimal with up to 2 decimal point. + Example: 0.01 or 60 + polling_interval: + Time interval in seconds at which the watchdog should poll the queues. + This should be decimal with + up to 3 decimal point. + Example: 0.005 or 60 + recovery_time: + Recovery-time in seconds after which stuck queue should + recover and start forwarding again. + This + should be decimal with up to 2 decimal point. + Example: 0.01 or 60 + override_action_drop: Override configured action on stuck queue to drop. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"all_off": {"type": bool}, "watchdog": {"type": Watchdog}, "_custom_data": {"type": dict}} + all_off: bool | None + """Disable PFC on all interfaces.""" + watchdog: Watchdog + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + all_off: bool | None | UndefinedType = Undefined, + watchdog: Watchdog | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PriorityFlowControl. + + + Subclass of AvdModel. + + Args: + all_off: Disable PFC on all interfaces. + watchdog: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Ptp(AvdModel): + """Subclass of AvdModel.""" + + class Source(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ip": {"type": str}, "_custom_data": {"type": dict}} + ip: str | None + """Source IP.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, ip: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Source. + + + Subclass of AvdModel. + + Args: + ip: Source IP. + _custom_data: _custom_data + + """ + + class MessageType(AvdModel): + """Subclass of AvdModel.""" + + class General(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"dscp": {"type": int}, "_custom_data": {"type": dict}} + dscp: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, dscp: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + General. + + + Subclass of AvdModel. + + Args: + dscp: dscp + _custom_data: _custom_data + + """ + + class Event(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"dscp": {"type": int}, "_custom_data": {"type": dict}} + dscp: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, dscp: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Event. + + + Subclass of AvdModel. + + Args: + dscp: dscp + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"general": {"type": General}, "event": {"type": Event}, "_custom_data": {"type": dict}} + general: General + """Subclass of AvdModel.""" + event: Event + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + general: General | UndefinedType = Undefined, + event: Event | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MessageType. + + + Subclass of AvdModel. + + Args: + general: Subclass of AvdModel. + event: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Monitor(AvdModel): + """Subclass of AvdModel.""" + + class Threshold(AvdModel): + """Subclass of AvdModel.""" + + class Drop(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"offset_from_master": {"type": int}, "mean_path_delay": {"type": int}, "_custom_data": {"type": dict}} + offset_from_master: int | None + mean_path_delay: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + offset_from_master: int | None | UndefinedType = Undefined, + mean_path_delay: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Drop. + + + Subclass of AvdModel. + + Args: + offset_from_master: offset_from_master + mean_path_delay: mean_path_delay + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "offset_from_master": {"type": int}, + "mean_path_delay": {"type": int}, + "drop": {"type": Drop}, + "_custom_data": {"type": dict}, + } + offset_from_master: int | None + mean_path_delay: int | None + drop: Drop + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + offset_from_master: int | None | UndefinedType = Undefined, + mean_path_delay: int | None | UndefinedType = Undefined, + drop: Drop | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Threshold. + + + Subclass of AvdModel. + + Args: + offset_from_master: offset_from_master + mean_path_delay: mean_path_delay + drop: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MissingMessage(AvdModel): + """Subclass of AvdModel.""" + + class Intervals(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"announce": {"type": int}, "follow_up": {"type": int}, "sync": {"type": int}, "_custom_data": {"type": dict}} + announce: int | None + follow_up: int | None + sync: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + announce: int | None | UndefinedType = Undefined, + follow_up: int | None | UndefinedType = Undefined, + sync: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Intervals. + + + Subclass of AvdModel. + + Args: + announce: announce + follow_up: follow_up + sync: sync + _custom_data: _custom_data + + """ + + class SequenceIds(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "announce": {"type": int}, + "delay_resp": {"type": int}, + "follow_up": {"type": int}, + "sync": {"type": int}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + announce: int | None + delay_resp: int | None + follow_up: int | None + sync: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + announce: int | None | UndefinedType = Undefined, + delay_resp: int | None | UndefinedType = Undefined, + follow_up: int | None | UndefinedType = Undefined, + sync: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceIds. + + + Subclass of AvdModel. + + Args: + enabled: enabled + announce: announce + delay_resp: delay_resp + follow_up: follow_up + sync: sync + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"intervals": {"type": Intervals}, "sequence_ids": {"type": SequenceIds}, "_custom_data": {"type": dict}} + intervals: Intervals + """Subclass of AvdModel.""" + sequence_ids: SequenceIds + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + intervals: Intervals | UndefinedType = Undefined, + sequence_ids: SequenceIds | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingMessage. + + + Subclass of AvdModel. + + Args: + intervals: Subclass of AvdModel. + sequence_ids: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "threshold": {"type": Threshold}, + "missing_message": {"type": MissingMessage}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + threshold: Threshold + """Subclass of AvdModel.""" + missing_message: MissingMessage + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + threshold: Threshold | UndefinedType = Undefined, + missing_message: MissingMessage | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Monitor. + + + Subclass of AvdModel. + + Args: + enabled: enabled + threshold: Subclass of AvdModel. + missing_message: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "mode": {"type": str}, + "profile": {"type": str}, + "mode_one_step": {"type": bool}, + "forward_unicast": {"type": bool}, + "clock_identity": {"type": str}, + "source": {"type": Source}, + "priority1": {"type": int}, + "priority2": {"type": int}, + "ttl": {"type": int}, + "domain": {"type": int}, + "message_type": {"type": MessageType}, + "monitor": {"type": Monitor}, + "_custom_data": {"type": dict}, + } + mode: Literal["boundary", "disabled", "e2etransparent", "gptp", "ordinarymaster", "p2ptransparent"] | None + profile: Literal["g8275.1", "g8275.2"] | None + mode_one_step: bool | None + forward_unicast: bool | None + clock_identity: str | None + """The clock-id in xx:xx:xx:xx:xx:xx format.""" + source: Source + """Subclass of AvdModel.""" + priority1: int | None + priority2: int | None + ttl: int | None + domain: int | None + message_type: MessageType + """Subclass of AvdModel.""" + monitor: Monitor + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["boundary", "disabled", "e2etransparent", "gptp", "ordinarymaster", "p2ptransparent"] | None | UndefinedType = Undefined, + profile: Literal["g8275.1", "g8275.2"] | None | UndefinedType = Undefined, + mode_one_step: bool | None | UndefinedType = Undefined, + forward_unicast: bool | None | UndefinedType = Undefined, + clock_identity: str | None | UndefinedType = Undefined, + source: Source | UndefinedType = Undefined, + priority1: int | None | UndefinedType = Undefined, + priority2: int | None | UndefinedType = Undefined, + ttl: int | None | UndefinedType = Undefined, + domain: int | None | UndefinedType = Undefined, + message_type: MessageType | UndefinedType = Undefined, + monitor: Monitor | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ptp. + + + Subclass of AvdModel. + + Args: + mode: mode + profile: profile + mode_one_step: mode_one_step + forward_unicast: forward_unicast + clock_identity: The clock-id in xx:xx:xx:xx:xx:xx format. + source: Subclass of AvdModel. + priority1: priority1 + priority2: priority2 + ttl: ttl + domain: domain + message_type: Subclass of AvdModel. + monitor: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Qos(AvdModel): + """Subclass of AvdModel.""" + + class Map(AvdModel): + """Subclass of AvdModel.""" + + class Cos(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Cos._item_type = str + + class Dscp(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Dscp._item_type = str + + class Exp(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Exp._item_type = str + + class TrafficClass(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + TrafficClass._item_type = str + + _fields: ClassVar[dict] = { + "cos": {"type": Cos}, + "dscp": {"type": Dscp}, + "exp": {"type": Exp}, + "traffic_class": {"type": TrafficClass}, + "_custom_data": {"type": dict}, + } + cos: Cos + """Subclass of AvdList with `str` items.""" + dscp: Dscp + """Subclass of AvdList with `str` items.""" + exp: Exp + """Subclass of AvdList with `str` items.""" + traffic_class: TrafficClass + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + cos: Cos | UndefinedType = Undefined, + dscp: Dscp | UndefinedType = Undefined, + exp: Exp | UndefinedType = Undefined, + traffic_class: TrafficClass | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Map. + + + Subclass of AvdModel. + + Args: + cos: Subclass of AvdList with `str` items. + dscp: Subclass of AvdList with `str` items. + exp: Subclass of AvdList with `str` items. + traffic_class: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class RandomDetect(AvdModel): + """Subclass of AvdModel.""" + + class Ecn(AvdModel): + """Subclass of AvdModel.""" + + class AllowNonEct(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "chip_based": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + """ + Allow non-ect and set drop-precedence 1 in a policy map simultaneously. + Check which command is + required for your platform. + """ + chip_based: bool | None + """Allow non-ect chip-based.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + chip_based: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AllowNonEct. + + + Subclass of AvdModel. + + Args: + enabled: + Allow non-ect and set drop-precedence 1 in a policy map simultaneously. + Check which command is + required for your platform. + chip_based: Allow non-ect chip-based. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"allow_non_ect": {"type": AllowNonEct}, "_custom_data": {"type": dict}} + allow_non_ect: AllowNonEct + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, allow_non_ect: AllowNonEct | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Ecn. + + + Subclass of AvdModel. + + Args: + allow_non_ect: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ecn": {"type": Ecn}, "_custom_data": {"type": dict}} + ecn: Ecn + """ + Global ECN Configuration. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, ecn: Ecn | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + RandomDetect. + + + Subclass of AvdModel. + + Args: + ecn: + Global ECN Configuration. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "map": {"type": Map}, + "rewrite_dscp": {"type": bool}, + "random_detect": {"type": RandomDetect}, + "_custom_data": {"type": dict}, + } + map: Map + """Subclass of AvdModel.""" + rewrite_dscp: bool | None + random_detect: RandomDetect + """ + Global random-detect settings. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + map: Map | UndefinedType = Undefined, + rewrite_dscp: bool | None | UndefinedType = Undefined, + random_detect: RandomDetect | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Qos. + + + Subclass of AvdModel. + + Args: + map: Subclass of AvdModel. + rewrite_dscp: rewrite_dscp + random_detect: + Global random-detect settings. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class QosProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class Shape(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"rate": {"type": str}, "_custom_data": {"type": dict}} + rate: str | None + """ + Supported options are platform dependent. + Example: "< rate > kbps", "1-100 percent", "< rate > pps" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, rate: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Shape. + + + Subclass of AvdModel. + + Args: + rate: + Supported options are platform dependent. + Example: "< rate > kbps", "1-100 percent", "< rate > pps" + _custom_data: _custom_data + + """ + + class ServicePolicy(AvdModel): + """Subclass of AvdModel.""" + + class Type(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"qos_input": {"type": str}, "_custom_data": {"type": dict}} + qos_input: str | None + """Policy-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, qos_input: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Type. + + + Subclass of AvdModel. + + Args: + qos_input: Policy-map name. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"type": {"type": Type}, "_custom_data": {"type": dict}} + type: Type + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, type: Type | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + ServicePolicy. + + + Subclass of AvdModel. + + Args: + type: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class TxQueuesItem(AvdModel): + """Subclass of AvdModel.""" + + class Shape(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"rate": {"type": str}, "_custom_data": {"type": dict}} + rate: str | None + """ + Supported options are platform dependent. + Example: "< rate > kbps", "1-100 percent", "< rate > pps" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, rate: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Shape. + + + Subclass of AvdModel. + + Args: + rate: + Supported options are platform dependent. + Example: "< rate > kbps", "1-100 percent", "< rate > pps" + _custom_data: _custom_data + + """ + + class RandomDetect(AvdModel): + """Subclass of AvdModel.""" + + class Ecn(AvdModel): + """Subclass of AvdModel.""" + + class Threshold(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "units": {"type": str}, + "min": {"type": int}, + "max": {"type": int}, + "max_probability": {"type": int}, + "weight": {"type": int}, + "_custom_data": {"type": dict}, + } + units: Literal["segments", "bytes", "kbytes", "mbytes", "milliseconds"] + """ + Units to be used for the threshold values. + This should be one of segments, byte, kbytes, mbytes. + """ + min: int + """Random-detect ECN minimum-threshold.""" + max: int + """Random-detect ECN maximum-threshold.""" + max_probability: int | None + """Random-detect ECN maximum mark probability.""" + weight: int | None + """Random-detect ECN weight.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + units: Literal["segments", "bytes", "kbytes", "mbytes", "milliseconds"] | UndefinedType = Undefined, + min: int | UndefinedType = Undefined, + max: int | UndefinedType = Undefined, + max_probability: int | None | UndefinedType = Undefined, + weight: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Threshold. + + + Subclass of AvdModel. + + Args: + units: + Units to be used for the threshold values. + This should be one of segments, byte, kbytes, mbytes. + min: Random-detect ECN minimum-threshold. + max: Random-detect ECN maximum-threshold. + max_probability: Random-detect ECN maximum mark probability. + weight: Random-detect ECN weight. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"count": {"type": bool}, "threshold": {"type": Threshold}, "_custom_data": {"type": dict}} + count: bool | None + """Enable counter for random-detect ECNs.""" + threshold: Threshold + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + count: bool | None | UndefinedType = Undefined, + threshold: Threshold | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ecn. + + + Subclass of AvdModel. + + Args: + count: Enable counter for random-detect ECNs. + threshold: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Drop(AvdModel): + """Subclass of AvdModel.""" + + class Threshold(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "units": {"type": str}, + "drop_precedence": {"type": int}, + "min": {"type": int}, + "max": {"type": int}, + "drop_probability": {"type": int}, + "weight": {"type": int}, + "_custom_data": {"type": dict}, + } + units: Literal["segments", "bytes", "kbytes", "mbytes", "microseconds", "milliseconds"] + """Units to be used for the threshold values.""" + drop_precedence: int | None + """Specify Drop Precedence value.""" + min: int + """WRED minimum-threshold.""" + max: int + """WRED maximum-threshold.""" + drop_probability: int + """WRED drop probability.""" + weight: int | None + """WRED weight.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + units: Literal["segments", "bytes", "kbytes", "mbytes", "microseconds", "milliseconds"] | UndefinedType = Undefined, + drop_precedence: int | None | UndefinedType = Undefined, + min: int | UndefinedType = Undefined, + max: int | UndefinedType = Undefined, + drop_probability: int | UndefinedType = Undefined, + weight: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Threshold. + + + Subclass of AvdModel. + + Args: + units: Units to be used for the threshold values. + drop_precedence: Specify Drop Precedence value. + min: WRED minimum-threshold. + max: WRED maximum-threshold. + drop_probability: WRED drop probability. + weight: WRED weight. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"threshold": {"type": Threshold}, "_custom_data": {"type": dict}} + threshold: Threshold + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, threshold: Threshold | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Drop. + + + Subclass of AvdModel. + + Args: + threshold: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ecn": {"type": Ecn}, "drop": {"type": Drop}, "_custom_data": {"type": dict}} + ecn: Ecn + """ + Explicit Congestion Notification. + + Subclass of AvdModel. + """ + drop: Drop + """ + Set WRED parameters. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ecn: Ecn | UndefinedType = Undefined, + drop: Drop | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RandomDetect. + + + Subclass of AvdModel. + + Args: + ecn: + Explicit Congestion Notification. + + Subclass of AvdModel. + drop: + Set WRED parameters. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "bandwidth_percent": {"type": int}, + "bandwidth_guaranteed_percent": {"type": int}, + "priority": {"type": str}, + "shape": {"type": Shape}, + "comment": {"type": str}, + "random_detect": {"type": RandomDetect}, + "_custom_data": {"type": dict}, + } + id: int + """TX-Queue ID.""" + bandwidth_percent: int | None + bandwidth_guaranteed_percent: int | None + priority: Literal["priority strict", "no priority"] | None + shape: Shape + """Subclass of AvdModel.""" + comment: str | None + """Text comment added to queue.""" + random_detect: RandomDetect + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + bandwidth_percent: int | None | UndefinedType = Undefined, + bandwidth_guaranteed_percent: int | None | UndefinedType = Undefined, + priority: Literal["priority strict", "no priority"] | None | UndefinedType = Undefined, + shape: Shape | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + random_detect: RandomDetect | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TxQueuesItem. + + + Subclass of AvdModel. + + Args: + id: TX-Queue ID. + bandwidth_percent: bandwidth_percent + bandwidth_guaranteed_percent: bandwidth_guaranteed_percent + priority: priority + shape: Subclass of AvdModel. + comment: Text comment added to queue. + random_detect: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class TxQueues(AvdIndexedList[int, TxQueuesItem]): + """Subclass of AvdIndexedList with `TxQueuesItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + TxQueues._item_type = TxQueuesItem + + class UcTxQueuesItem(AvdModel): + """Subclass of AvdModel.""" + + class Shape(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"rate": {"type": str}, "_custom_data": {"type": dict}} + rate: str | None + """ + Supported options are platform dependent. + Example: "< rate > kbps", "1-100 percent", "< rate > pps" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, rate: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Shape. + + + Subclass of AvdModel. + + Args: + rate: + Supported options are platform dependent. + Example: "< rate > kbps", "1-100 percent", "< rate > pps" + _custom_data: _custom_data + + """ + + class RandomDetect(AvdModel): + """Subclass of AvdModel.""" + + class Ecn(AvdModel): + """Subclass of AvdModel.""" + + class Threshold(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "units": {"type": str}, + "min": {"type": int}, + "max": {"type": int}, + "max_probability": {"type": int}, + "weight": {"type": int}, + "_custom_data": {"type": dict}, + } + units: Literal["segments", "bytes", "kbytes", "mbytes", "milliseconds"] + """Unit to be used for the threshold values.""" + min: int + """Random-detect ECN minimum-threshold.""" + max: int + """Random-detect ECN maximum-threshold.""" + max_probability: int | None + """Random-detect ECN maximum mark probability.""" + weight: int | None + """Random-detect ECN weight.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + units: Literal["segments", "bytes", "kbytes", "mbytes", "milliseconds"] | UndefinedType = Undefined, + min: int | UndefinedType = Undefined, + max: int | UndefinedType = Undefined, + max_probability: int | None | UndefinedType = Undefined, + weight: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Threshold. + + + Subclass of AvdModel. + + Args: + units: Unit to be used for the threshold values. + min: Random-detect ECN minimum-threshold. + max: Random-detect ECN maximum-threshold. + max_probability: Random-detect ECN maximum mark probability. + weight: Random-detect ECN weight. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"count": {"type": bool}, "threshold": {"type": Threshold}, "_custom_data": {"type": dict}} + count: bool | None + """Enable counter for random-detect ECNs.""" + threshold: Threshold + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + count: bool | None | UndefinedType = Undefined, + threshold: Threshold | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ecn. + + + Subclass of AvdModel. + + Args: + count: Enable counter for random-detect ECNs. + threshold: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Drop(AvdModel): + """Subclass of AvdModel.""" + + class Threshold(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "units": {"type": str}, + "drop_precedence": {"type": int}, + "min": {"type": int}, + "max": {"type": int}, + "drop_probability": {"type": int}, + "weight": {"type": int}, + "_custom_data": {"type": dict}, + } + units: Literal["segments", "bytes", "kbytes", "mbytes", "microseconds", "milliseconds"] + """Units to be used for the threshold values.""" + drop_precedence: int | None + """Specify Drop Precedence value.""" + min: int + """WRED minimum-threshold.""" + max: int + """WRED maximum-threshold.""" + drop_probability: int + """WRED drop probability.""" + weight: int | None + """WRED weight.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + units: Literal["segments", "bytes", "kbytes", "mbytes", "microseconds", "milliseconds"] | UndefinedType = Undefined, + drop_precedence: int | None | UndefinedType = Undefined, + min: int | UndefinedType = Undefined, + max: int | UndefinedType = Undefined, + drop_probability: int | UndefinedType = Undefined, + weight: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Threshold. + + + Subclass of AvdModel. + + Args: + units: Units to be used for the threshold values. + drop_precedence: Specify Drop Precedence value. + min: WRED minimum-threshold. + max: WRED maximum-threshold. + drop_probability: WRED drop probability. + weight: WRED weight. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"threshold": {"type": Threshold}, "_custom_data": {"type": dict}} + threshold: Threshold + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, threshold: Threshold | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Drop. + + + Subclass of AvdModel. + + Args: + threshold: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ecn": {"type": Ecn}, "drop": {"type": Drop}, "_custom_data": {"type": dict}} + ecn: Ecn + """ + Explicit Congestion Notification. + + Subclass of AvdModel. + """ + drop: Drop + """ + Set WRED parameters. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ecn: Ecn | UndefinedType = Undefined, + drop: Drop | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RandomDetect. + + + Subclass of AvdModel. + + Args: + ecn: + Explicit Congestion Notification. + + Subclass of AvdModel. + drop: + Set WRED parameters. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "bandwidth_percent": {"type": int}, + "bandwidth_guaranteed_percent": {"type": int}, + "priority": {"type": str}, + "shape": {"type": Shape}, + "comment": {"type": str}, + "random_detect": {"type": RandomDetect}, + "_custom_data": {"type": dict}, + } + id: int + """UC TX queue ID.""" + bandwidth_percent: int | None + bandwidth_guaranteed_percent: int | None + priority: Literal["priority strict", "no priority"] | None + shape: Shape + """Subclass of AvdModel.""" + comment: str | None + """Text comment added to queue.""" + random_detect: RandomDetect + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + bandwidth_percent: int | None | UndefinedType = Undefined, + bandwidth_guaranteed_percent: int | None | UndefinedType = Undefined, + priority: Literal["priority strict", "no priority"] | None | UndefinedType = Undefined, + shape: Shape | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + random_detect: RandomDetect | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + UcTxQueuesItem. + + + Subclass of AvdModel. + + Args: + id: UC TX queue ID. + bandwidth_percent: bandwidth_percent + bandwidth_guaranteed_percent: bandwidth_guaranteed_percent + priority: priority + shape: Subclass of AvdModel. + comment: Text comment added to queue. + random_detect: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class UcTxQueues(AvdIndexedList[int, UcTxQueuesItem]): + """Subclass of AvdIndexedList with `UcTxQueuesItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + UcTxQueues._item_type = UcTxQueuesItem + + class McTxQueuesItem(AvdModel): + """Subclass of AvdModel.""" + + class Shape(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"rate": {"type": str}, "_custom_data": {"type": dict}} + rate: str | None + """ + Supported options are platform dependent. + Example: "< rate > kbps", "1-100 percent", "< rate > pps" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, rate: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Shape. + + + Subclass of AvdModel. + + Args: + rate: + Supported options are platform dependent. + Example: "< rate > kbps", "1-100 percent", "< rate > pps" + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "bandwidth_percent": {"type": int}, + "bandwidth_guaranteed_percent": {"type": int}, + "priority": {"type": str}, + "shape": {"type": Shape}, + "comment": {"type": str}, + "_custom_data": {"type": dict}, + } + id: int + """MC TX queue ID.""" + bandwidth_percent: int | None + bandwidth_guaranteed_percent: int | None + priority: Literal["priority strict", "no priority"] | None + shape: Shape + """Subclass of AvdModel.""" + comment: str | None + """Text comment added to queue.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + bandwidth_percent: int | None | UndefinedType = Undefined, + bandwidth_guaranteed_percent: int | None | UndefinedType = Undefined, + priority: Literal["priority strict", "no priority"] | None | UndefinedType = Undefined, + shape: Shape | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + McTxQueuesItem. + + + Subclass of AvdModel. + + Args: + id: MC TX queue ID. + bandwidth_percent: bandwidth_percent + bandwidth_guaranteed_percent: bandwidth_guaranteed_percent + priority: priority + shape: Subclass of AvdModel. + comment: Text comment added to queue. + _custom_data: _custom_data + + """ + + class McTxQueues(AvdIndexedList[int, McTxQueuesItem]): + """Subclass of AvdIndexedList with `McTxQueuesItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + McTxQueues._item_type = McTxQueuesItem + + class PriorityFlowControl(AvdModel): + """Subclass of AvdModel.""" + + class Watchdog(AvdModel): + """Subclass of AvdModel.""" + + class Timer(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "timeout": {"type": str}, + "polling_interval": {"type": str}, + "recovery_time": {"type": str}, + "forced": {"type": bool}, + "_custom_data": {"type": dict}, + } + timeout: str + """ + Timeout in seconds after which port should be errdisabled or + should start dropping on congested + priorities. + This should be decimal with up to 2 decimal point. + Example: 0.01 or 60 + """ + polling_interval: str + """ + Time interval in seconds at which the watchdog should poll the queues. + This should be decimal with + up to 3 decimal point or set + to 'auto' based on recovery_time and timeout values. + Example: 0.005 or + 60 + """ + recovery_time: str + """ + Recovery-time in seconds after which stuck queue should + recover and start forwarding again. + This + should be decimal with up to 2 decimal point. + Example: 0.01 or 60 + """ + forced: bool | None + """ + Force recover any stuck queue(s) after the duration, + irrespective of whether PFC frames are being + received or not. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + timeout: str | UndefinedType = Undefined, + polling_interval: str | UndefinedType = Undefined, + recovery_time: str | UndefinedType = Undefined, + forced: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Timer. + + + Subclass of AvdModel. + + Args: + timeout: + Timeout in seconds after which port should be errdisabled or + should start dropping on congested + priorities. + This should be decimal with up to 2 decimal point. + Example: 0.01 or 60 + polling_interval: + Time interval in seconds at which the watchdog should poll the queues. + This should be decimal with + up to 3 decimal point or set + to 'auto' based on recovery_time and timeout values. + Example: 0.005 or + 60 + recovery_time: + Recovery-time in seconds after which stuck queue should + recover and start forwarding again. + This + should be decimal with up to 2 decimal point. + Example: 0.01 or 60 + forced: + Force recover any stuck queue(s) after the duration, + irrespective of whether PFC frames are being + received or not. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "action": {"type": str}, "timer": {"type": Timer}, "_custom_data": {"type": dict}} + enabled: bool + """Enable the watchdog on stuck transmit queues.""" + action: Literal["drop", "notify-only"] | None + """ + Override the default error-disable action to either drop + traffic on the stuck queue or notify-only + without making any actions on the stuck queue. + """ + timer: Timer + """ + Timer thresholds whilst monitoring queues. + + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + action: Literal["drop", "notify-only"] | None | UndefinedType = Undefined, + timer: Timer | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Watchdog. + + + Subclass of AvdModel. + + Args: + enabled: Enable the watchdog on stuck transmit queues. + action: + Override the default error-disable action to either drop + traffic on the stuck queue or notify-only + without making any actions on the stuck queue. + timer: + Timer thresholds whilst monitoring queues. + + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PrioritiesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"priority": {"type": int}, "no_drop": {"type": bool}, "_custom_data": {"type": dict}} + priority: int + """Priority queue number (COS value).""" + no_drop: bool + """Enable Priority Flow Control frames on this queue.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + priority: int | UndefinedType = Undefined, + no_drop: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PrioritiesItem. + + + Subclass of AvdModel. + + Args: + priority: Priority queue number (COS value). + no_drop: Enable Priority Flow Control frames on this queue. + _custom_data: _custom_data + + """ + + class Priorities(AvdIndexedList[int, PrioritiesItem]): + """Subclass of AvdIndexedList with `PrioritiesItem` items. Primary key is `priority` (`int`).""" + + _primary_key: ClassVar[str] = "priority" + + Priorities._item_type = PrioritiesItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "watchdog": {"type": Watchdog}, + "priorities": {"type": Priorities}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Enable Priority Flow control.""" + watchdog: Watchdog + """ + Watchdog can detect stuck transmit queues. + + + Subclass of AvdModel. + """ + priorities: Priorities + """ + Set the drop/no_drop on each queue. + + + Subclass of AvdIndexedList with `PrioritiesItem` items. + Primary key is `priority` (`int`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + watchdog: Watchdog | UndefinedType = Undefined, + priorities: Priorities | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PriorityFlowControl. + + + Subclass of AvdModel. + + Args: + enabled: Enable Priority Flow control. + watchdog: + Watchdog can detect stuck transmit queues. + + + Subclass of AvdModel. + priorities: + Set the drop/no_drop on each queue. + + + Subclass of AvdIndexedList with `PrioritiesItem` items. + Primary key is `priority` (`int`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "trust": {"type": str}, + "cos": {"type": int}, + "dscp": {"type": int}, + "shape": {"type": Shape}, + "service_policy": {"type": ServicePolicy}, + "tx_queues": {"type": TxQueues}, + "uc_tx_queues": {"type": UcTxQueues}, + "mc_tx_queues": {"type": McTxQueues}, + "priority_flow_control": {"type": PriorityFlowControl}, + "_custom_data": {"type": dict}, + } + name: str + """Profile-Name.""" + trust: Literal["cos", "dscp", "disabled"] | None + cos: int | None + dscp: int | None + shape: Shape + """Subclass of AvdModel.""" + service_policy: ServicePolicy + """Subclass of AvdModel.""" + tx_queues: TxQueues + """Subclass of AvdIndexedList with `TxQueuesItem` items. Primary key is `id` (`int`).""" + uc_tx_queues: UcTxQueues + """Subclass of AvdIndexedList with `UcTxQueuesItem` items. Primary key is `id` (`int`).""" + mc_tx_queues: McTxQueues + """Subclass of AvdIndexedList with `McTxQueuesItem` items. Primary key is `id` (`int`).""" + priority_flow_control: PriorityFlowControl + """ + Priority Flow Control settings. + + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + trust: Literal["cos", "dscp", "disabled"] | None | UndefinedType = Undefined, + cos: int | None | UndefinedType = Undefined, + dscp: int | None | UndefinedType = Undefined, + shape: Shape | UndefinedType = Undefined, + service_policy: ServicePolicy | UndefinedType = Undefined, + tx_queues: TxQueues | UndefinedType = Undefined, + uc_tx_queues: UcTxQueues | UndefinedType = Undefined, + mc_tx_queues: McTxQueues | UndefinedType = Undefined, + priority_flow_control: PriorityFlowControl | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + QosProfilesItem. + + + Subclass of AvdModel. + + Args: + name: Profile-Name. + trust: trust + cos: cos + dscp: dscp + shape: Subclass of AvdModel. + service_policy: Subclass of AvdModel. + tx_queues: Subclass of AvdIndexedList with `TxQueuesItem` items. Primary key is `id` (`int`). + uc_tx_queues: Subclass of AvdIndexedList with `UcTxQueuesItem` items. Primary key is `id` (`int`). + mc_tx_queues: Subclass of AvdIndexedList with `McTxQueuesItem` items. Primary key is `id` (`int`). + priority_flow_control: + Priority Flow Control settings. + + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class QosProfiles(AvdIndexedList[str, QosProfilesItem]): + """Subclass of AvdIndexedList with `QosProfilesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + QosProfiles._item_type = QosProfilesItem + + class QueueMonitorLength(AvdModel): + """Subclass of AvdModel.""" + + class DefaultThresholds(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"high": {"type": int}, "low": {"type": int}, "_custom_data": {"type": dict}} + high: int + """Default high threshold for Ethernet Interfaces.""" + low: int | None + """ + Default low threshold for Ethernet Interfaces. + Low threshold support is platform dependent. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + high: int | UndefinedType = Undefined, + low: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultThresholds. + + + Subclass of AvdModel. + + Args: + high: Default high threshold for Ethernet Interfaces. + low: + Default low threshold for Ethernet Interfaces. + Low threshold support is platform dependent. + _custom_data: _custom_data + + """ + + class Cpu(AvdModel): + """Subclass of AvdModel.""" + + class Thresholds(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"high": {"type": int}, "low": {"type": int}, "_custom_data": {"type": dict}} + high: int + low: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + high: int | UndefinedType = Undefined, + low: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Thresholds. + + + Subclass of AvdModel. + + Args: + high: high + low: low + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"thresholds": {"type": Thresholds}, "_custom_data": {"type": dict}} + thresholds: Thresholds + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, thresholds: Thresholds | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Cpu. + + + Subclass of AvdModel. + + Args: + thresholds: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "default_thresholds": {"type": DefaultThresholds}, + "log": {"type": int}, + "notifying": {"type": bool}, + "cpu": {"type": Cpu}, + "tx_latency": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + default_thresholds: DefaultThresholds + """Subclass of AvdModel.""" + log: int | None + """Logging interval in seconds.""" + notifying: bool | None + """Should only be used for platforms supporting the "queue-monitor length notifying" CLI.""" + cpu: Cpu + """Subclass of AvdModel.""" + tx_latency: bool | None + """Enable tx-latency mode.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + default_thresholds: DefaultThresholds | UndefinedType = Undefined, + log: int | None | UndefinedType = Undefined, + notifying: bool | None | UndefinedType = Undefined, + cpu: Cpu | UndefinedType = Undefined, + tx_latency: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + QueueMonitorLength. + + + Subclass of AvdModel. + + Args: + enabled: enabled + default_thresholds: Subclass of AvdModel. + log: Logging interval in seconds. + notifying: Should only be used for platforms supporting the "queue-monitor length notifying" CLI. + cpu: Subclass of AvdModel. + tx_latency: Enable tx-latency mode. + _custom_data: _custom_data + + """ + + class QueueMonitorStreaming(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enable": {"type": bool}, + "ip_access_group": {"type": str}, + "ipv6_access_group": {"type": str}, + "max_connections": {"type": int}, + "vrf": {"type": str}, + "_custom_data": {"type": dict}, + } + enable: bool | None + ip_access_group: str | None + """Name of IP ACL.""" + ipv6_access_group: str | None + """Name of IPv6 ACL.""" + max_connections: int | None + vrf: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enable: bool | None | UndefinedType = Undefined, + ip_access_group: str | None | UndefinedType = Undefined, + ipv6_access_group: str | None | UndefinedType = Undefined, + max_connections: int | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + QueueMonitorStreaming. + + + Subclass of AvdModel. + + Args: + enable: enable + ip_access_group: Name of IP ACL. + ipv6_access_group: Name of IPv6 ACL. + max_connections: max_connections + vrf: vrf + _custom_data: _custom_data + + """ + + class RadiusServer(AvdModel): + """Subclass of AvdModel.""" + + class Attribute32IncludeInAccessReq(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"hostname": {"type": bool}, "format": {"type": str}, "_custom_data": {"type": dict}} + hostname: bool | None + format: str | None + """Specify the format of the NAS-Identifier. If 'hostname' is set, this is ignored.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: bool | None | UndefinedType = Undefined, + format: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Attribute32IncludeInAccessReq. + + + Subclass of AvdModel. + + Args: + hostname: hostname + format: Specify the format of the NAS-Identifier. If 'hostname' is set, this is ignored. + _custom_data: _custom_data + + """ + + class DynamicAuthorization(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"port": {"type": int}, "tls_ssl_profile": {"type": str}, "_custom_data": {"type": dict}} + port: int | None + """TCP Port.""" + tls_ssl_profile: str | None + """Name of TLS profile.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + port: int | None | UndefinedType = Undefined, + tls_ssl_profile: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DynamicAuthorization. + + + Subclass of AvdModel. + + Args: + port: TCP Port. + tls_ssl_profile: Name of TLS profile. + _custom_data: _custom_data + + """ + + class HostsItem(AvdModel): + """Subclass of AvdModel.""" + + class Tls(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "ssl_profile": {"type": str}, "port": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool | None + """Enable TLS for radius-server.""" + ssl_profile: str | None + """Name of TLS profile.""" + port: int | None + """TCP Port used for TLS. EOS default is 2083.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + ssl_profile: str | None | UndefinedType = Undefined, + port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Tls. + + + Subclass of AvdModel. + + Args: + enabled: Enable TLS for radius-server. + ssl_profile: Name of TLS profile. + port: TCP Port used for TLS. EOS default is 2083. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "host": {"type": str}, + "vrf": {"type": str}, + "tls": {"type": Tls}, + "timeout": {"type": int}, + "retransmit": {"type": int}, + "key": {"type": str}, + "_custom_data": {"type": dict}, + } + host: str + """Host IP address or name.""" + vrf: str | None + tls: Tls + """ + When TLS is configured, `key` is ignored.. + + Subclass of AvdModel. + """ + timeout: int | None + retransmit: int | None + key: str | None + """ + Encrypted key - only type 7 supported. + When TLS is configured, `key` is ignored. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + host: str | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + tls: Tls | UndefinedType = Undefined, + timeout: int | None | UndefinedType = Undefined, + retransmit: int | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + HostsItem. + + + Subclass of AvdModel. + + Args: + host: Host IP address or name. + vrf: vrf + tls: + When TLS is configured, `key` is ignored.. + + Subclass of AvdModel. + timeout: timeout + retransmit: retransmit + key: + Encrypted key - only type 7 supported. + When TLS is configured, `key` is ignored. + _custom_data: _custom_data + + """ + + class Hosts(AvdIndexedList[str, HostsItem]): + """Subclass of AvdIndexedList with `HostsItem` items. Primary key is `host` (`str`).""" + + _primary_key: ClassVar[str] = "host" + + Hosts._item_type = HostsItem + + _fields: ClassVar[dict] = { + "attribute_32_include_in_access_req": {"type": Attribute32IncludeInAccessReq}, + "deadtime": {"type": int}, + "dynamic_authorization": {"type": DynamicAuthorization}, + "hosts": {"type": Hosts}, + "tls_ssl_profile": {"type": str}, + "_custom_data": {"type": dict}, + } + attribute_32_include_in_access_req: Attribute32IncludeInAccessReq + """Subclass of AvdModel.""" + deadtime: int | None + """Time to skip a non-responsive server in minutes.""" + dynamic_authorization: DynamicAuthorization + """Subclass of AvdModel.""" + hosts: Hosts + """Subclass of AvdIndexedList with `HostsItem` items. Primary key is `host` (`str`).""" + tls_ssl_profile: str | None + """Name of global TLS profile.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + attribute_32_include_in_access_req: Attribute32IncludeInAccessReq | UndefinedType = Undefined, + deadtime: int | None | UndefinedType = Undefined, + dynamic_authorization: DynamicAuthorization | UndefinedType = Undefined, + hosts: Hosts | UndefinedType = Undefined, + tls_ssl_profile: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RadiusServer. + + + Subclass of AvdModel. + + Args: + attribute_32_include_in_access_req: Subclass of AvdModel. + deadtime: Time to skip a non-responsive server in minutes. + dynamic_authorization: Subclass of AvdModel. + hosts: Subclass of AvdIndexedList with `HostsItem` items. Primary key is `host` (`str`). + tls_ssl_profile: Name of global TLS profile. + _custom_data: _custom_data + + """ + + class Redundancy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"protocol": {"type": str}, "_custom_data": {"type": dict}} + protocol: str | None + """Redundancy Protocol.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, protocol: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Redundancy. + + + Subclass of AvdModel. + + Args: + protocol: Redundancy Protocol. + _custom_data: _custom_data + + """ + + class RolesItem(AvdModel): + """Subclass of AvdModel.""" + + class SequenceNumbersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "sequence": {"type": int}, + "action": {"type": str}, + "mode": {"type": str}, + "command": {"type": str}, + "_custom_data": {"type": dict}, + } + sequence: int | None + """Sequence number.""" + action: Literal["permit", "deny"] | None + mode: str | None + """"config", "config-all", "exec" or mode key as string.""" + command: str | None + """Command as string.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sequence: int | None | UndefinedType = Undefined, + action: Literal["permit", "deny"] | None | UndefinedType = Undefined, + mode: str | None | UndefinedType = Undefined, + command: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceNumbersItem. + + + Subclass of AvdModel. + + Args: + sequence: Sequence number. + action: action + mode: "config", "config-all", "exec" or mode key as string. + command: Command as string. + _custom_data: _custom_data + + """ + + class SequenceNumbers(AvdList[SequenceNumbersItem]): + """Subclass of AvdList with `SequenceNumbersItem` items.""" + + SequenceNumbers._item_type = SequenceNumbersItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "sequence_numbers": {"type": SequenceNumbers}, "_custom_data": {"type": dict}} + name: str + """Role name.""" + sequence_numbers: SequenceNumbers + """Subclass of AvdList with `SequenceNumbersItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + sequence_numbers: SequenceNumbers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RolesItem. + + + Subclass of AvdModel. + + Args: + name: Role name. + sequence_numbers: Subclass of AvdList with `SequenceNumbersItem` items. + _custom_data: _custom_data + + """ + + class Roles(AvdIndexedList[str, RolesItem]): + """Subclass of AvdIndexedList with `RolesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Roles._item_type = RolesItem + + class RouteMapsItem(AvdModel): + """Subclass of AvdModel.""" + + class SequenceNumbersItem(AvdModel): + """Subclass of AvdModel.""" + + class Match(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Match._item_type = str + + class Set(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Set._item_type = str + + class Continue(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "sequence_number": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool | None + sequence_number: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + sequence_number: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Continue. + + + Subclass of AvdModel. + + Args: + enabled: enabled + sequence_number: sequence_number + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "sequence": {"type": int}, + "type": {"type": str}, + "description": {"type": str}, + "match": {"type": Match}, + "set": {"type": Set}, + "sub_route_map": {"type": str}, + "field_continue": {"type": Continue}, + "_custom_data": {"type": dict}, + } + _field_to_key_map: ClassVar[dict] = {"field_continue": "continue"} + _key_to_field_map: ClassVar[dict] = {"continue": "field_continue"} + sequence: int + """Sequence ID.""" + type: Literal["permit", "deny"] + description: str | None + match: Match + """ + List of "match" statements. + + Subclass of AvdList with `str` items. + """ + set: Set + """ + List of "set" statements. + + Subclass of AvdList with `str` items. + """ + sub_route_map: str | None + """Name of Sub-Route-map.""" + field_continue: Continue + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sequence: int | UndefinedType = Undefined, + type: Literal["permit", "deny"] | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + match: Match | UndefinedType = Undefined, + set: Set | UndefinedType = Undefined, + sub_route_map: str | None | UndefinedType = Undefined, + field_continue: Continue | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceNumbersItem. + + + Subclass of AvdModel. + + Args: + sequence: Sequence ID. + type: type + description: description + match: + List of "match" statements. + + Subclass of AvdList with `str` items. + set: + List of "set" statements. + + Subclass of AvdList with `str` items. + sub_route_map: Name of Sub-Route-map. + field_continue: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class SequenceNumbers(AvdIndexedList[int, SequenceNumbersItem]): + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + + _primary_key: ClassVar[str] = "sequence" + + SequenceNumbers._item_type = SequenceNumbersItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "sequence_numbers": {"type": SequenceNumbers}, "_custom_data": {"type": dict}} + name: str + """Route-map Name.""" + sequence_numbers: SequenceNumbers + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + sequence_numbers: SequenceNumbers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouteMapsItem. + + + Subclass of AvdModel. + + Args: + name: Route-map Name. + sequence_numbers: Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`). + _custom_data: _custom_data + + """ + + class RouteMaps(AvdIndexedList[str, RouteMapsItem]): + """Subclass of AvdIndexedList with `RouteMapsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + RouteMaps._item_type = RouteMapsItem + + class RouterAdaptiveVirtualTopology(AvdModel): + """Subclass of AvdModel.""" + + class Region(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "id": {"type": int}, "_custom_data": {"type": dict}} + name: str + id: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + id: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Region. + + + Subclass of AvdModel. + + Args: + name: name + id: id + _custom_data: _custom_data + + """ + + class Zone(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "id": {"type": int}, "_custom_data": {"type": dict}} + name: str + id: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + id: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Zone. + + + Subclass of AvdModel. + + Args: + name: name + id: id + _custom_data: _custom_data + + """ + + class Site(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "id": {"type": int}, "_custom_data": {"type": dict}} + name: str + id: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + id: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Site. + + + Subclass of AvdModel. + + Args: + name: name + id: id + _custom_data: _custom_data + + """ + + class ProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "load_balance_policy": {"type": str}, + "internet_exit_policy": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """AVT Name.""" + load_balance_policy: str | None + """Name of the load-balance policy.""" + internet_exit_policy: str | None + """Name of the internet exit policy.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + load_balance_policy: str | None | UndefinedType = Undefined, + internet_exit_policy: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ProfilesItem. + + + Subclass of AvdModel. + + Args: + name: AVT Name. + load_balance_policy: Name of the load-balance policy. + internet_exit_policy: Name of the internet exit policy. + _custom_data: _custom_data + + """ + + class Profiles(AvdIndexedList[str, ProfilesItem]): + """Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Profiles._item_type = ProfilesItem + + class PoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + class MatchesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "application_profile": {"type": str}, + "avt_profile": {"type": str}, + "dscp": {"type": int}, + "traffic_class": {"type": int}, + "_custom_data": {"type": dict}, + } + application_profile: str | None + """Application profile name.""" + avt_profile: str | None + """AVT Profile name.""" + dscp: int | None + """Set DSCP for matched traffic.""" + traffic_class: int | None + """Set traffic-class for matched traffic.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + application_profile: str | None | UndefinedType = Undefined, + avt_profile: str | None | UndefinedType = Undefined, + dscp: int | None | UndefinedType = Undefined, + traffic_class: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchesItem. + + + Subclass of AvdModel. + + Args: + application_profile: Application profile name. + avt_profile: AVT Profile name. + dscp: Set DSCP for matched traffic. + traffic_class: Set traffic-class for matched traffic. + _custom_data: _custom_data + + """ + + class Matches(AvdList[MatchesItem]): + """Subclass of AvdList with `MatchesItem` items.""" + + Matches._item_type = MatchesItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "matches": {"type": Matches}, "_custom_data": {"type": dict}} + name: str + """Policy name.""" + matches: Matches + """Subclass of AvdList with `MatchesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + matches: Matches | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PoliciesItem. + + + Subclass of AvdModel. + + Args: + name: Policy name. + matches: Subclass of AvdList with `MatchesItem` items. + _custom_data: _custom_data + + """ + + class Policies(AvdIndexedList[str, PoliciesItem]): + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Policies._item_type = PoliciesItem + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + class ProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "id": {"type": int}, "_custom_data": {"type": dict}} + name: str | None + """AVT profile name.""" + id: int + """Unique ID for this AVT (per VRF).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + id: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ProfilesItem. + + + Subclass of AvdModel. + + Args: + name: AVT profile name. + id: Unique ID for this AVT (per VRF). + _custom_data: _custom_data + + """ + + class Profiles(AvdIndexedList[int, ProfilesItem]): + """Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + Profiles._item_type = ProfilesItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "policy": {"type": str}, "profiles": {"type": Profiles}, "_custom_data": {"type": dict}} + name: str + """VRF name.""" + policy: str | None + """AVT Policy name.""" + profiles: Profiles + """ + AVT profiles in this VRF. + + Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `id` + (`int`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + policy: str | None | UndefinedType = Undefined, + profiles: Profiles | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: VRF name. + policy: AVT Policy name. + profiles: + AVT profiles in this VRF. + + Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `id` + (`int`). + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + _fields: ClassVar[dict] = { + "topology_role": {"type": str}, + "gateway_vxlan": {"type": bool}, + "region": {"type": Region}, + "zone": {"type": Zone}, + "site": {"type": Site}, + "profiles": {"type": Profiles}, + "policies": {"type": Policies}, + "vrfs": {"type": Vrfs}, + "_custom_data": {"type": dict}, + } + topology_role: Literal["edge", "pathfinder", "transit region", "transit zone"] | None + """Role name.""" + gateway_vxlan: bool | None + """ + Enables VXLAN gateway router profile. + Only applicable for `topology_role: edge`, `topology_role: + transit region` or `topology_role: transit zone`. + """ + region: Region + """ + Region name and ID. + + Subclass of AvdModel. + """ + zone: Zone + """ + Zone name and ID. + + Subclass of AvdModel. + """ + site: Site + """ + Site name and ID. + + Subclass of AvdModel. + """ + profiles: Profiles + """Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `name` (`str`).""" + policies: Policies + """ + A sequence of application profiles mapped to some virtual topologies. + + Subclass of AvdIndexedList + with `PoliciesItem` items. Primary key is `name` (`str`). + """ + vrfs: Vrfs + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + topology_role: Literal["edge", "pathfinder", "transit region", "transit zone"] | None | UndefinedType = Undefined, + gateway_vxlan: bool | None | UndefinedType = Undefined, + region: Region | UndefinedType = Undefined, + zone: Zone | UndefinedType = Undefined, + site: Site | UndefinedType = Undefined, + profiles: Profiles | UndefinedType = Undefined, + policies: Policies | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouterAdaptiveVirtualTopology. + + + Subclass of AvdModel. + + Args: + topology_role: Role name. + gateway_vxlan: + Enables VXLAN gateway router profile. + Only applicable for `topology_role: edge`, `topology_role: + transit region` or `topology_role: transit zone`. + region: + Region name and ID. + + Subclass of AvdModel. + zone: + Zone name and ID. + + Subclass of AvdModel. + site: + Site name and ID. + + Subclass of AvdModel. + profiles: Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `name` (`str`). + policies: + A sequence of application profiles mapped to some virtual topologies. + + Subclass of AvdIndexedList + with `PoliciesItem` items. Primary key is `name` (`str`). + vrfs: Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class RouterBfd(AvdModel): + """Subclass of AvdModel.""" + + class Multihop(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interval": {"type": int}, "min_rx": {"type": int}, "multiplier": {"type": int}, "_custom_data": {"type": dict}} + interval: int | None + """Rate in milliseconds.""" + min_rx: int | None + """Rate in milliseconds.""" + multiplier: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | None | UndefinedType = Undefined, + min_rx: int | None | UndefinedType = Undefined, + multiplier: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Multihop. + + + Subclass of AvdModel. + + Args: + interval: Rate in milliseconds. + min_rx: Rate in milliseconds. + multiplier: multiplier + _custom_data: _custom_data + + """ + + class Sbfd(AvdModel): + """Subclass of AvdModel.""" + + class LocalInterface(AvdModel): + """Subclass of AvdModel.""" + + class Protocols(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4": {"type": bool}, "ipv6": {"type": bool}, "_custom_data": {"type": dict}} + ipv4: bool | None + ipv6: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4: bool | None | UndefinedType = Undefined, + ipv6: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Protocols. + + + Subclass of AvdModel. + + Args: + ipv4: ipv4 + ipv6: ipv6 + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"name": {"type": str}, "protocols": {"type": Protocols}, "_custom_data": {"type": dict}} + name: str | None + """Interface Name.""" + protocols: Protocols + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + protocols: Protocols | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LocalInterface. + + + Subclass of AvdModel. + + Args: + name: Interface Name. + protocols: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Reflector(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"min_rx": {"type": int}, "local_discriminator": {"type": str}, "_custom_data": {"type": dict}} + min_rx: int | None + """Rate in milliseconds.""" + local_discriminator: str | None + """IPv4 address or 32 bit integer.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + min_rx: int | None | UndefinedType = Undefined, + local_discriminator: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Reflector. + + + Subclass of AvdModel. + + Args: + min_rx: Rate in milliseconds. + local_discriminator: IPv4 address or 32 bit integer. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "local_interface": {"type": LocalInterface}, + "initiator_interval": {"type": int}, + "initiator_multiplier": {"type": int}, + "initiator_measurement_round_trip": {"type": bool}, + "reflector": {"type": Reflector}, + "_custom_data": {"type": dict}, + } + local_interface: LocalInterface + """Subclass of AvdModel.""" + initiator_interval: int | None + """Rate in milliseconds.""" + initiator_multiplier: int | None + initiator_measurement_round_trip: bool | None + """Enable round-trip delay measurement.""" + reflector: Reflector + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + local_interface: LocalInterface | UndefinedType = Undefined, + initiator_interval: int | None | UndefinedType = Undefined, + initiator_multiplier: int | None | UndefinedType = Undefined, + initiator_measurement_round_trip: bool | None | UndefinedType = Undefined, + reflector: Reflector | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Sbfd. + + + Subclass of AvdModel. + + Args: + local_interface: Subclass of AvdModel. + initiator_interval: Rate in milliseconds. + initiator_multiplier: initiator_multiplier + initiator_measurement_round_trip: Enable round-trip delay measurement. + reflector: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "interval": {"type": int}, + "local_address": {"type": str}, + "min_rx": {"type": int}, + "multiplier": {"type": int}, + "multihop": {"type": Multihop}, + "session_snapshot_interval": {"type": int}, + "session_snapshot_interval_dangerous": {"type": bool}, + "sbfd": {"type": Sbfd}, + "slow_timer": {"type": int}, + "_custom_data": {"type": dict}, + } + interval: int | None + """Rate in milliseconds.""" + local_address: str | None + """Configure BFD local IP/IPv6 address.""" + min_rx: int | None + """Rate in milliseconds.""" + multiplier: int | None + multihop: Multihop + """Subclass of AvdModel.""" + session_snapshot_interval: int | None + """ + Interval in seconds. + Intervals below 10 are considered "dangerous" on EOS and must have + `session_snapshot_interval_dangerous` set to `true`. + """ + session_snapshot_interval_dangerous: bool | None + sbfd: Sbfd + """Subclass of AvdModel.""" + slow_timer: int | None + """Rate in milliseconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | None | UndefinedType = Undefined, + local_address: str | None | UndefinedType = Undefined, + min_rx: int | None | UndefinedType = Undefined, + multiplier: int | None | UndefinedType = Undefined, + multihop: Multihop | UndefinedType = Undefined, + session_snapshot_interval: int | None | UndefinedType = Undefined, + session_snapshot_interval_dangerous: bool | None | UndefinedType = Undefined, + sbfd: Sbfd | UndefinedType = Undefined, + slow_timer: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouterBfd. + + + Subclass of AvdModel. + + Args: + interval: Rate in milliseconds. + local_address: Configure BFD local IP/IPv6 address. + min_rx: Rate in milliseconds. + multiplier: multiplier + multihop: Subclass of AvdModel. + session_snapshot_interval: + Interval in seconds. + Intervals below 10 are considered "dangerous" on EOS and must have + `session_snapshot_interval_dangerous` set to `true`. + session_snapshot_interval_dangerous: session_snapshot_interval_dangerous + sbfd: Subclass of AvdModel. + slow_timer: Rate in milliseconds. + _custom_data: _custom_data + + """ + + class RouterBgp(AvdModel): + """Subclass of AvdModel.""" + + class Timers(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "keepalive_time": {"type": int}, + "hold_time": {"type": int}, + "min_hold_time": {"type": int}, + "send_failure_hold_time": {"type": int}, + "_custom_data": {"type": dict}, + } + keepalive_time: int | None + """ + Time between BGP keepalive messages in seconds. + `keepalive_time` should be lesser than `hold_time`. + """ + hold_time: int | None + """ + Hold time in seconds. Must be defined along with `keepalive_time`. + The valid values are 3-7200 or 0 + if both values are 0. + """ + min_hold_time: int | None + """ + Neighbor's minimum hold time constraint in seconds. + `min_hold_time` should be less than `hold_time`. + """ + send_failure_hold_time: int | None + """Send failure hold time in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + keepalive_time: int | None | UndefinedType = Undefined, + hold_time: int | None | UndefinedType = Undefined, + min_hold_time: int | None | UndefinedType = Undefined, + send_failure_hold_time: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Timers. + + + Subclass of AvdModel. + + Args: + keepalive_time: + Time between BGP keepalive messages in seconds. + `keepalive_time` should be lesser than `hold_time`. + hold_time: + Hold time in seconds. Must be defined along with `keepalive_time`. + The valid values are 3-7200 or 0 + if both values are 0. + min_hold_time: + Neighbor's minimum hold time constraint in seconds. + `min_hold_time` should be less than `hold_time`. + send_failure_hold_time: Send failure hold time in seconds. + _custom_data: _custom_data + + """ + + class Distance(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "external_routes": {"type": int}, + "internal_routes": {"type": int}, + "local_routes": {"type": int}, + "_custom_data": {"type": dict}, + } + external_routes: int + internal_routes: int + local_routes: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + external_routes: int | UndefinedType = Undefined, + internal_routes: int | UndefinedType = Undefined, + local_routes: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Distance. + + + Subclass of AvdModel. + + Args: + external_routes: external_routes + internal_routes: internal_routes + local_routes: local_routes + _custom_data: _custom_data + + """ + + class GracefulRestart(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "restart_time": {"type": int}, + "stalepath_time": {"type": int}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + restart_time: int | None + """Number of seconds.""" + stalepath_time: int | None + """Number of seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + restart_time: int | None | UndefinedType = Undefined, + stalepath_time: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GracefulRestart. + + + Subclass of AvdModel. + + Args: + enabled: enabled + restart_time: Number of seconds. + stalepath_time: Number of seconds. + _custom_data: _custom_data + + """ + + class GracefulRestartHelper(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "restart_time": {"type": int}, "long_lived": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + restart_time: int | None + """ + Number of seconds + graceful-restart-help long-lived and restart-time are mutually exclusive in CLI. + restart-time will take precedence if both are configured. + """ + long_lived: bool | None + """ + graceful-restart-help long-lived and restart-time are mutually exclusive in CLI. + restart-time will + take precedence if both are configured. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + restart_time: int | None | UndefinedType = Undefined, + long_lived: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GracefulRestartHelper. + + + Subclass of AvdModel. + + Args: + enabled: enabled + restart_time: + Number of seconds + graceful-restart-help long-lived and restart-time are mutually exclusive in CLI. + restart-time will take precedence if both are configured. + long_lived: + graceful-restart-help long-lived and restart-time are mutually exclusive in CLI. + restart-time will + take precedence if both are configured. + _custom_data: _custom_data + + """ + + class MaximumPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"paths": {"type": int}, "ecmp": {"type": int}, "_custom_data": {"type": dict}} + paths: int + ecmp: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + paths: int | UndefinedType = Undefined, + ecmp: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MaximumPaths. + + + Subclass of AvdModel. + + Args: + paths: paths + ecmp: ecmp + _custom_data: _custom_data + + """ + + class Updates(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"wait_for_convergence": {"type": bool}, "wait_install": {"type": bool}, "_custom_data": {"type": dict}} + wait_for_convergence: bool | None + """ + Disables FIB updates and route advertisement when the BGP instance is initiated until the BGP + convergence state is reached. + """ + wait_install: bool | None + """ + Do not advertise reachability to a prefix until that prefix has been installed in hardware. + This + will eliminate any temporary black holes due to a BGP speaker advertising reachability to a prefix + that may not yet be installed into the forwarding plane. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + wait_for_convergence: bool | None | UndefinedType = Undefined, + wait_install: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Updates. + + + Subclass of AvdModel. + + Args: + wait_for_convergence: + Disables FIB updates and route advertisement when the BGP instance is initiated until the BGP + convergence state is reached. + wait_install: + Do not advertise reachability to a prefix until that prefix has been installed in hardware. + This + will eliminate any temporary black holes due to a BGP speaker advertising reachability to a prefix + that may not yet be installed into the forwarding plane. + _custom_data: _custom_data + + """ + + class BgpDefaults(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + BgpDefaults._item_type = str + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class Default(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4_unicast": {"type": bool}, "ipv4_unicast_transport_ipv6": {"type": bool}, "_custom_data": {"type": dict}} + ipv4_unicast: bool | None + """Default activation of IPv4 unicast address-family on all IPv4 neighbors (EOS default = True).""" + ipv4_unicast_transport_ipv6: bool | None + """Default activation of IPv4 unicast address-family on all IPv6 neighbors (EOS default == False).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4_unicast: bool | None | UndefinedType = Undefined, + ipv4_unicast_transport_ipv6: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Default. + + + Subclass of AvdModel. + + Args: + ipv4_unicast: Default activation of IPv4 unicast address-family on all IPv4 neighbors (EOS default = True). + ipv4_unicast_transport_ipv6: Default activation of IPv4 unicast address-family on all IPv6 neighbors (EOS default == False). + _custom_data: _custom_data + + """ + + class RouteReflectorPreserveAttributes(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "always": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + always: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + always: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouteReflectorPreserveAttributes. + + + Subclass of AvdModel. + + Args: + enabled: enabled + always: always + _custom_data: _custom_data + + """ + + class Bestpath(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"d_path": {"type": bool}, "_custom_data": {"type": dict}} + d_path: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, d_path: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Bestpath. + + + Subclass of AvdModel. + + Args: + d_path: d_path + _custom_data: _custom_data + + """ + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "send": {"type": str}, "send_limit": {"type": int}, "_custom_data": {"type": dict}} + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "default": {"type": Default}, + "route_reflector_preserve_attributes": {"type": RouteReflectorPreserveAttributes}, + "bestpath": {"type": Bestpath}, + "additional_paths": {"type": AdditionalPaths}, + "redistribute_internal": {"type": bool}, + "_custom_data": {"type": dict}, + } + default: Default + """Subclass of AvdModel.""" + route_reflector_preserve_attributes: RouteReflectorPreserveAttributes + """Subclass of AvdModel.""" + bestpath: Bestpath + """Subclass of AvdModel.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + redistribute_internal: bool | None + """Allow redistribution of iBGP routes into an Interior Gateway Protocol (IGP). EOS default is true.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + default: Default | UndefinedType = Undefined, + route_reflector_preserve_attributes: RouteReflectorPreserveAttributes | UndefinedType = Undefined, + bestpath: Bestpath | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + redistribute_internal: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + default: Subclass of AvdModel. + route_reflector_preserve_attributes: Subclass of AvdModel. + bestpath: Subclass of AvdModel. + additional_paths: Subclass of AvdModel. + redistribute_internal: Allow redistribution of iBGP routes into an Interior Gateway Protocol (IGP). EOS default is true. + _custom_data: _custom_data + + """ + + class ListenRangesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "prefix": {"type": str}, + "peer_id_include_router_id": {"type": bool}, + "peer_group": {"type": str}, + "peer_filter": {"type": str}, + "remote_as": {"type": str}, + "_custom_data": {"type": dict}, + } + prefix: str | None + """IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I".""" + peer_id_include_router_id: bool | None + """Include router ID as part of peer filter.""" + peer_group: str | None + """Peer group name.""" + peer_filter: str | None + """ + Peer-filter name. + note: `peer_filter` or `remote_as` is required but mutually exclusive. + If both are + defined, `peer_filter` takes precedence + """ + remote_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix: str | None | UndefinedType = Undefined, + peer_id_include_router_id: bool | None | UndefinedType = Undefined, + peer_group: str | None | UndefinedType = Undefined, + peer_filter: str | None | UndefinedType = Undefined, + remote_as: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ListenRangesItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I". + peer_id_include_router_id: Include router ID as part of peer filter. + peer_group: Peer group name. + peer_filter: + Peer-filter name. + note: `peer_filter` or `remote_as` is required but mutually exclusive. + If both are + defined, `peer_filter` takes precedence + remote_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + _custom_data: _custom_data + + """ + + class ListenRanges(AvdList[ListenRangesItem]): + """Subclass of AvdList with `ListenRangesItem` items.""" + + ListenRanges._item_type = ListenRangesItem + + class NeighborDefault(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"send_community": {"type": str}, "_custom_data": {"type": dict}} + send_community: ( + Literal["all", "large", "extended", "standard", "extended large", "standard large", "standard extended", "standard extended large"] | None + ) + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + send_community: Literal[ + "all", "large", "extended", "standard", "extended large", "standard large", "standard extended", "standard extended large" + ] + | None + | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborDefault. + + + Subclass of AvdModel. + + Args: + send_community: send_community + _custom_data: _custom_data + + """ + + class PeerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class AsPath(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"remote_as_replace_out": {"type": bool}, "prepend_own_disabled": {"type": bool}, "_custom_data": {"type": dict}} + remote_as_replace_out: bool | None + """Replace AS number with local AS number.""" + prepend_own_disabled: bool | None + """Disable prepending own AS number to AS path.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + remote_as_replace_out: bool | None | UndefinedType = Undefined, + prepend_own_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AsPath. + + + Subclass of AvdModel. + + Args: + remote_as_replace_out: Replace AS number with local AS number. + prepend_own_disabled: Disable prepending own AS number to AS path. + _custom_data: _custom_data + + """ + + class RemovePrivateAs(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "all": {"type": bool}, "replace_as": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + all: bool | None + replace_as: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + all: bool | None | UndefinedType = Undefined, + replace_as: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemovePrivateAs. + + + Subclass of AvdModel. + + Args: + enabled: enabled + all: all + replace_as: replace_as + _custom_data: _custom_data + + """ + + class RemovePrivateAsIngress(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "replace_as": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + replace_as: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + replace_as: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemovePrivateAsIngress. + + + Subclass of AvdModel. + + Args: + enabled: enabled + replace_as: replace_as + _custom_data: _custom_data + + """ + + class BfdTimers(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interval": {"type": int}, "min_rx": {"type": int}, "multiplier": {"type": int}, "_custom_data": {"type": dict}} + interval: int + """Interval in milliseconds.""" + min_rx: int + """Rate in milliseconds.""" + multiplier: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | UndefinedType = Undefined, + min_rx: int | UndefinedType = Undefined, + multiplier: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BfdTimers. + + + Subclass of AvdModel. + + Args: + interval: Interval in milliseconds. + min_rx: Rate in milliseconds. + multiplier: multiplier + _custom_data: _custom_data + + """ + + class DefaultOriginate(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "always": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + always: bool | None + route_map: str | None + """Route-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + always: bool | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultOriginate. + + + Subclass of AvdModel. + + Args: + enabled: enabled + always: always + route_map: Route-map name. + _custom_data: _custom_data + + """ + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + class DirectionIn(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "action": {"type": str}, + "include_community_list": {"type": bool}, + "include_prefix_list": {"type": bool}, + "include_sub_route_map": {"type": bool}, + "_custom_data": {"type": dict}, + } + action: Literal["deny", "permit", "deny-in-out"] + """Missing policy action.""" + include_community_list: bool | None + """Include community-list references in missing policy decision.""" + include_prefix_list: bool | None + """Include prefix-list references in missing policy decision.""" + include_sub_route_map: bool | None + """Include sub-route-map references in missing policy decision.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["deny", "permit", "deny-in-out"] | UndefinedType = Undefined, + include_community_list: bool | None | UndefinedType = Undefined, + include_prefix_list: bool | None | UndefinedType = Undefined, + include_sub_route_map: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionIn. + + + Subclass of AvdModel. + + Args: + action: Missing policy action. + include_community_list: Include community-list references in missing policy decision. + include_prefix_list: Include prefix-list references in missing policy decision. + include_sub_route_map: Include sub-route-map references in missing policy decision. + _custom_data: _custom_data + + """ + + class DirectionOut(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "action": {"type": str}, + "include_community_list": {"type": bool}, + "include_prefix_list": {"type": bool}, + "include_sub_route_map": {"type": bool}, + "_custom_data": {"type": dict}, + } + action: Literal["deny", "permit", "deny-in-out"] + """Missing policy action.""" + include_community_list: bool | None + """Include community-list references in missing policy decision.""" + include_prefix_list: bool | None + """Include prefix-list references in missing policy decision.""" + include_sub_route_map: bool | None + """Include sub-route-map references in missing policy decision.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["deny", "permit", "deny-in-out"] | UndefinedType = Undefined, + include_community_list: bool | None | UndefinedType = Undefined, + include_prefix_list: bool | None | UndefinedType = Undefined, + include_sub_route_map: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionOut. + + + Subclass of AvdModel. + + Args: + action: Missing policy action. + include_community_list: Include community-list references in missing policy decision. + include_prefix_list: Include prefix-list references in missing policy decision. + include_sub_route_map: Include sub-route-map references in missing policy decision. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"direction_in": {"type": DirectionIn}, "direction_out": {"type": DirectionOut}, "_custom_data": {"type": dict}} + direction_in: DirectionIn + """ + Missing policy inbound direction. + + Subclass of AvdModel. + """ + direction_out: DirectionOut + """ + Missing policy outbound direction. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in: DirectionIn | UndefinedType = Undefined, + direction_out: DirectionOut | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in: + Missing policy inbound direction. + + Subclass of AvdModel. + direction_out: + Missing policy outbound direction. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class LinkBandwidth(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "default": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + default: str | None + """nn.nn(K|M|G) link speed in bits/second.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + default: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkBandwidth. + + + Subclass of AvdModel. + + Args: + enabled: enabled + default: nn.nn(K|M|G) link speed in bits/second. + _custom_data: _custom_data + + """ + + class AllowasIn(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "times": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool | None + times: int | None + """Number of local ASNs allowed in a BGP update.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + times: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AllowasIn. + + + Subclass of AvdModel. + + Args: + enabled: enabled + times: Number of local ASNs allowed in a BGP update. + _custom_data: _custom_data + + """ + + class RibInPrePolicyRetain(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "all": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + all: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + all: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RibInPrePolicyRetain. + + + Subclass of AvdModel. + + Args: + enabled: enabled + all: all + _custom_data: _custom_data + + """ + + class SharedSecret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "hash_algorithm": {"type": str}, "_custom_data": {"type": dict}} + profile: str + """Name of profile defined under `management_security`.""" + hash_algorithm: Literal["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"] + """Note: Algorithm hmac-sha-256 requires EOS version 4.31.1F and above.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + hash_algorithm: Literal["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SharedSecret. + + + Subclass of AvdModel. + + Args: + profile: Name of profile defined under `management_security`. + hash_algorithm: Note: Algorithm hmac-sha-256 requires EOS version 4.31.1F and above. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "type": {"type": str}, + "remote_as": {"type": str}, + "local_as": {"type": str}, + "description": {"type": str}, + "shutdown": {"type": bool}, + "as_path": {"type": AsPath}, + "remove_private_as": {"type": RemovePrivateAs}, + "remove_private_as_ingress": {"type": RemovePrivateAsIngress}, + "next_hop_unchanged": {"type": bool}, + "update_source": {"type": str}, + "route_reflector_client": {"type": bool}, + "bfd": {"type": bool}, + "bfd_timers": {"type": BfdTimers}, + "ebgp_multihop": {"type": int}, + "next_hop_self": {"type": bool}, + "password": {"type": str}, + "passive": {"type": bool}, + "default_originate": {"type": DefaultOriginate}, + "send_community": {"type": str}, + "maximum_routes": {"type": int}, + "maximum_routes_warning_limit": {"type": str}, + "maximum_routes_warning_only": {"type": bool}, + "missing_policy": {"type": MissingPolicy}, + "link_bandwidth": {"type": LinkBandwidth}, + "allowas_in": {"type": AllowasIn}, + "weight": {"type": int}, + "timers": {"type": str}, + "rib_in_pre_policy_retain": {"type": RibInPrePolicyRetain}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "session_tracker": {"type": str}, + "shared_secret": {"type": SharedSecret}, + "ttl_maximum_hops": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str + """Peer-group name.""" + type: str | None + """Key only used for documentation or validation purposes.""" + remote_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + local_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + description: str | None + shutdown: bool | None + as_path: AsPath + """ + BGP AS-PATH options. + + Subclass of AvdModel. + """ + remove_private_as: RemovePrivateAs + """ + Remove private AS numbers in outbound AS path. + + Subclass of AvdModel. + """ + remove_private_as_ingress: RemovePrivateAsIngress + """Subclass of AvdModel.""" + next_hop_unchanged: bool | None + update_source: str | None + """IP address or interface name.""" + route_reflector_client: bool | None + bfd: bool | None + """Enable BFD.""" + bfd_timers: BfdTimers + """ + Override default BFD timers. BFD must be enabled with `bfd: true`. + + Subclass of AvdModel. + """ + ebgp_multihop: int | None + """Time-to-live in range of hops.""" + next_hop_self: bool | None + password: str | None + passive: bool | None + default_originate: DefaultOriginate + """Subclass of AvdModel.""" + send_community: str | None + """'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'.""" + maximum_routes: int | None + """Maximum number of routes (0 means unlimited).""" + maximum_routes_warning_limit: str | None + """ + Maximum number of routes after which a warning is issued (0 means never warn) or + Percentage of + maximum number of routes at which to warn ("<1-100> percent"). + """ + maximum_routes_warning_only: bool | None + missing_policy: MissingPolicy + """ + Missing policy configuration for all address-families. + + Subclass of AvdModel. + """ + link_bandwidth: LinkBandwidth + """Subclass of AvdModel.""" + allowas_in: AllowasIn + """Subclass of AvdModel.""" + weight: int | None + timers: str | None + """BGP Keepalive and Hold Timer values in seconds as string "<0-3600> <0-3600>".""" + rib_in_pre_policy_retain: RibInPrePolicyRetain + """Subclass of AvdModel.""" + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + session_tracker: str | None + shared_secret: SharedSecret + """Subclass of AvdModel.""" + ttl_maximum_hops: int | None + """Maximum number of hops.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + type: str | None | UndefinedType = Undefined, + remote_as: str | None | UndefinedType = Undefined, + local_as: str | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + as_path: AsPath | UndefinedType = Undefined, + remove_private_as: RemovePrivateAs | UndefinedType = Undefined, + remove_private_as_ingress: RemovePrivateAsIngress | UndefinedType = Undefined, + next_hop_unchanged: bool | None | UndefinedType = Undefined, + update_source: str | None | UndefinedType = Undefined, + route_reflector_client: bool | None | UndefinedType = Undefined, + bfd: bool | None | UndefinedType = Undefined, + bfd_timers: BfdTimers | UndefinedType = Undefined, + ebgp_multihop: int | None | UndefinedType = Undefined, + next_hop_self: bool | None | UndefinedType = Undefined, + password: str | None | UndefinedType = Undefined, + passive: bool | None | UndefinedType = Undefined, + default_originate: DefaultOriginate | UndefinedType = Undefined, + send_community: str | None | UndefinedType = Undefined, + maximum_routes: int | None | UndefinedType = Undefined, + maximum_routes_warning_limit: str | None | UndefinedType = Undefined, + maximum_routes_warning_only: bool | None | UndefinedType = Undefined, + missing_policy: MissingPolicy | UndefinedType = Undefined, + link_bandwidth: LinkBandwidth | UndefinedType = Undefined, + allowas_in: AllowasIn | UndefinedType = Undefined, + weight: int | None | UndefinedType = Undefined, + timers: str | None | UndefinedType = Undefined, + rib_in_pre_policy_retain: RibInPrePolicyRetain | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + session_tracker: str | None | UndefinedType = Undefined, + shared_secret: SharedSecret | UndefinedType = Undefined, + ttl_maximum_hops: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Peer-group name. + type: Key only used for documentation or validation purposes. + remote_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + local_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + description: description + shutdown: shutdown + as_path: + BGP AS-PATH options. + + Subclass of AvdModel. + remove_private_as: + Remove private AS numbers in outbound AS path. + + Subclass of AvdModel. + remove_private_as_ingress: Subclass of AvdModel. + next_hop_unchanged: next_hop_unchanged + update_source: IP address or interface name. + route_reflector_client: route_reflector_client + bfd: Enable BFD. + bfd_timers: + Override default BFD timers. BFD must be enabled with `bfd: true`. + + Subclass of AvdModel. + ebgp_multihop: Time-to-live in range of hops. + next_hop_self: next_hop_self + password: password + passive: passive + default_originate: Subclass of AvdModel. + send_community: 'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'. + maximum_routes: Maximum number of routes (0 means unlimited). + maximum_routes_warning_limit: + Maximum number of routes after which a warning is issued (0 means never warn) or + Percentage of + maximum number of routes at which to warn ("<1-100> percent"). + maximum_routes_warning_only: maximum_routes_warning_only + missing_policy: + Missing policy configuration for all address-families. + + Subclass of AvdModel. + link_bandwidth: Subclass of AvdModel. + allowas_in: Subclass of AvdModel. + weight: weight + timers: BGP Keepalive and Hold Timer values in seconds as string "<0-3600> <0-3600>". + rib_in_pre_policy_retain: Subclass of AvdModel. + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + session_tracker: session_tracker + shared_secret: Subclass of AvdModel. + ttl_maximum_hops: Maximum number of hops. + _custom_data: _custom_data + + """ + + class PeerGroups(AvdIndexedList[str, PeerGroupsItem]): + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PeerGroups._item_type = PeerGroupsItem + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + class AsPath(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"remote_as_replace_out": {"type": bool}, "prepend_own_disabled": {"type": bool}, "_custom_data": {"type": dict}} + remote_as_replace_out: bool | None + """Replace AS number with local AS number.""" + prepend_own_disabled: bool | None + """Disable prepending own AS number to AS path.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + remote_as_replace_out: bool | None | UndefinedType = Undefined, + prepend_own_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AsPath. + + + Subclass of AvdModel. + + Args: + remote_as_replace_out: Replace AS number with local AS number. + prepend_own_disabled: Disable prepending own AS number to AS path. + _custom_data: _custom_data + + """ + + class BfdTimers(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interval": {"type": int}, "min_rx": {"type": int}, "multiplier": {"type": int}, "_custom_data": {"type": dict}} + interval: int + """Interval in milliseconds.""" + min_rx: int + """Rate in milliseconds.""" + multiplier: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | UndefinedType = Undefined, + min_rx: int | UndefinedType = Undefined, + multiplier: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BfdTimers. + + + Subclass of AvdModel. + + Args: + interval: Interval in milliseconds. + min_rx: Rate in milliseconds. + multiplier: multiplier + _custom_data: _custom_data + + """ + + class DefaultOriginate(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "always": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + always: bool | None + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + always: bool | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultOriginate. + + + Subclass of AvdModel. + + Args: + enabled: enabled + always: always + route_map: route_map + _custom_data: _custom_data + + """ + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + class DirectionIn(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "action": {"type": str}, + "include_community_list": {"type": bool}, + "include_prefix_list": {"type": bool}, + "include_sub_route_map": {"type": bool}, + "_custom_data": {"type": dict}, + } + action: Literal["deny", "permit", "deny-in-out"] + """Missing policy action.""" + include_community_list: bool | None + """Include community-list references in missing policy decision.""" + include_prefix_list: bool | None + """Include prefix-list references in missing policy decision.""" + include_sub_route_map: bool | None + """Include sub-route-map references in missing policy decision.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["deny", "permit", "deny-in-out"] | UndefinedType = Undefined, + include_community_list: bool | None | UndefinedType = Undefined, + include_prefix_list: bool | None | UndefinedType = Undefined, + include_sub_route_map: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionIn. + + + Subclass of AvdModel. + + Args: + action: Missing policy action. + include_community_list: Include community-list references in missing policy decision. + include_prefix_list: Include prefix-list references in missing policy decision. + include_sub_route_map: Include sub-route-map references in missing policy decision. + _custom_data: _custom_data + + """ + + class DirectionOut(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "action": {"type": str}, + "include_community_list": {"type": bool}, + "include_prefix_list": {"type": bool}, + "include_sub_route_map": {"type": bool}, + "_custom_data": {"type": dict}, + } + action: Literal["deny", "permit", "deny-in-out"] + """Missing policy action.""" + include_community_list: bool | None + """Include community-list references in missing policy decision.""" + include_prefix_list: bool | None + """Include prefix-list references in missing policy decision.""" + include_sub_route_map: bool | None + """Include sub-route-map references in missing policy decision.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["deny", "permit", "deny-in-out"] | UndefinedType = Undefined, + include_community_list: bool | None | UndefinedType = Undefined, + include_prefix_list: bool | None | UndefinedType = Undefined, + include_sub_route_map: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionOut. + + + Subclass of AvdModel. + + Args: + action: Missing policy action. + include_community_list: Include community-list references in missing policy decision. + include_prefix_list: Include prefix-list references in missing policy decision. + include_sub_route_map: Include sub-route-map references in missing policy decision. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"direction_in": {"type": DirectionIn}, "direction_out": {"type": DirectionOut}, "_custom_data": {"type": dict}} + direction_in: DirectionIn + """ + Missing policy inbound direction. + + Subclass of AvdModel. + """ + direction_out: DirectionOut + """ + Missing policy outbound direction. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in: DirectionIn | UndefinedType = Undefined, + direction_out: DirectionOut | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in: + Missing policy inbound direction. + + Subclass of AvdModel. + direction_out: + Missing policy outbound direction. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class AllowasIn(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "times": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool | None + times: int | None + """Number of local ASNs allowed in a BGP update.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + times: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AllowasIn. + + + Subclass of AvdModel. + + Args: + enabled: enabled + times: Number of local ASNs allowed in a BGP update. + _custom_data: _custom_data + + """ + + class LinkBandwidth(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "default": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + default: str | None + """nn.nn(K|M|G) link speed in bits/second.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + default: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkBandwidth. + + + Subclass of AvdModel. + + Args: + enabled: enabled + default: nn.nn(K|M|G) link speed in bits/second. + _custom_data: _custom_data + + """ + + class RibInPrePolicyRetain(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "all": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + all: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + all: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RibInPrePolicyRetain. + + + Subclass of AvdModel. + + Args: + enabled: enabled + all: all + _custom_data: _custom_data + + """ + + class RemovePrivateAs(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "all": {"type": bool}, "replace_as": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + all: bool | None + replace_as: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + all: bool | None | UndefinedType = Undefined, + replace_as: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemovePrivateAs. + + + Subclass of AvdModel. + + Args: + enabled: enabled + all: all + replace_as: replace_as + _custom_data: _custom_data + + """ + + class RemovePrivateAsIngress(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "replace_as": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + replace_as: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + replace_as: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemovePrivateAsIngress. + + + Subclass of AvdModel. + + Args: + enabled: enabled + replace_as: replace_as + _custom_data: _custom_data + + """ + + class SharedSecret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "hash_algorithm": {"type": str}, "_custom_data": {"type": dict}} + profile: str + """Name of profile defined under `management_security`.""" + hash_algorithm: Literal["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"] + """Note: Algorithm hmac-sha-256 requires EOS version 4.31.1F and above.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + hash_algorithm: Literal["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SharedSecret. + + + Subclass of AvdModel. + + Args: + profile: Name of profile defined under `management_security`. + hash_algorithm: Note: Algorithm hmac-sha-256 requires EOS version 4.31.1F and above. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "peer_group": {"type": str}, + "remote_as": {"type": str}, + "local_as": {"type": str}, + "as_path": {"type": AsPath}, + "peer": {"type": str}, + "description": {"type": str}, + "route_reflector_client": {"type": bool}, + "password": {"type": str}, + "passive": {"type": bool}, + "shutdown": {"type": bool}, + "update_source": {"type": str}, + "bfd": {"type": bool}, + "bfd_timers": {"type": BfdTimers}, + "weight": {"type": int}, + "timers": {"type": str}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "default_originate": {"type": DefaultOriginate}, + "send_community": {"type": str}, + "maximum_routes": {"type": int}, + "maximum_routes_warning_limit": {"type": str}, + "maximum_routes_warning_only": {"type": bool}, + "missing_policy": {"type": MissingPolicy}, + "allowas_in": {"type": AllowasIn}, + "ebgp_multihop": {"type": int}, + "next_hop_self": {"type": bool}, + "link_bandwidth": {"type": LinkBandwidth}, + "rib_in_pre_policy_retain": {"type": RibInPrePolicyRetain}, + "remove_private_as": {"type": RemovePrivateAs}, + "remove_private_as_ingress": {"type": RemovePrivateAsIngress}, + "session_tracker": {"type": str}, + "shared_secret": {"type": SharedSecret}, + "ttl_maximum_hops": {"type": int}, + "_custom_data": {"type": dict}, + } + ip_address: str + peer_group: str | None + remote_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + local_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + as_path: AsPath + """ + BGP AS-PATH options. + + Subclass of AvdModel. + """ + peer: str | None + """Key only used for documentation or validation purposes.""" + description: str | None + route_reflector_client: bool | None + password: str | None + passive: bool | None + shutdown: bool | None + update_source: str | None + """Source Interface.""" + bfd: bool | None + """Enable BFD.""" + bfd_timers: BfdTimers + """ + Override default BFD timers. BFD must be enabled with `bfd: true`. + + Subclass of AvdModel. + """ + weight: int | None + timers: str | None + """BGP Keepalive and Hold Timer values in seconds as string "<0-3600> <0-3600>".""" + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + default_originate: DefaultOriginate + """Subclass of AvdModel.""" + send_community: str | None + """'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'.""" + maximum_routes: int | None + """Maximum number of routes (0 means unlimited).""" + maximum_routes_warning_limit: str | None + """ + Maximum number of routes after which a warning is issued (0 means never warn) or + Percentage of + maximum number of routes at which to warn ("<1-100> percent"). + """ + maximum_routes_warning_only: bool | None + missing_policy: MissingPolicy + """ + Missing policy configuration for all address-families. + + Subclass of AvdModel. + """ + allowas_in: AllowasIn + """Subclass of AvdModel.""" + ebgp_multihop: int | None + """Time-to-live in range of hops.""" + next_hop_self: bool | None + link_bandwidth: LinkBandwidth + """Subclass of AvdModel.""" + rib_in_pre_policy_retain: RibInPrePolicyRetain + """Subclass of AvdModel.""" + remove_private_as: RemovePrivateAs + """ + Remove private AS numbers in outbound AS path. + + Subclass of AvdModel. + """ + remove_private_as_ingress: RemovePrivateAsIngress + """Subclass of AvdModel.""" + session_tracker: str | None + shared_secret: SharedSecret + """Subclass of AvdModel.""" + ttl_maximum_hops: int | None + """Maximum number of hops.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + peer_group: str | None | UndefinedType = Undefined, + remote_as: str | None | UndefinedType = Undefined, + local_as: str | None | UndefinedType = Undefined, + as_path: AsPath | UndefinedType = Undefined, + peer: str | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + route_reflector_client: bool | None | UndefinedType = Undefined, + password: str | None | UndefinedType = Undefined, + passive: bool | None | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + update_source: str | None | UndefinedType = Undefined, + bfd: bool | None | UndefinedType = Undefined, + bfd_timers: BfdTimers | UndefinedType = Undefined, + weight: int | None | UndefinedType = Undefined, + timers: str | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + default_originate: DefaultOriginate | UndefinedType = Undefined, + send_community: str | None | UndefinedType = Undefined, + maximum_routes: int | None | UndefinedType = Undefined, + maximum_routes_warning_limit: str | None | UndefinedType = Undefined, + maximum_routes_warning_only: bool | None | UndefinedType = Undefined, + missing_policy: MissingPolicy | UndefinedType = Undefined, + allowas_in: AllowasIn | UndefinedType = Undefined, + ebgp_multihop: int | None | UndefinedType = Undefined, + next_hop_self: bool | None | UndefinedType = Undefined, + link_bandwidth: LinkBandwidth | UndefinedType = Undefined, + rib_in_pre_policy_retain: RibInPrePolicyRetain | UndefinedType = Undefined, + remove_private_as: RemovePrivateAs | UndefinedType = Undefined, + remove_private_as_ingress: RemovePrivateAsIngress | UndefinedType = Undefined, + session_tracker: str | None | UndefinedType = Undefined, + shared_secret: SharedSecret | UndefinedType = Undefined, + ttl_maximum_hops: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + peer_group: peer_group + remote_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + local_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + as_path: + BGP AS-PATH options. + + Subclass of AvdModel. + peer: Key only used for documentation or validation purposes. + description: description + route_reflector_client: route_reflector_client + password: password + passive: passive + shutdown: shutdown + update_source: Source Interface. + bfd: Enable BFD. + bfd_timers: + Override default BFD timers. BFD must be enabled with `bfd: true`. + + Subclass of AvdModel. + weight: weight + timers: BGP Keepalive and Hold Timer values in seconds as string "<0-3600> <0-3600>". + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + default_originate: Subclass of AvdModel. + send_community: 'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'. + maximum_routes: Maximum number of routes (0 means unlimited). + maximum_routes_warning_limit: + Maximum number of routes after which a warning is issued (0 means never warn) or + Percentage of + maximum number of routes at which to warn ("<1-100> percent"). + maximum_routes_warning_only: maximum_routes_warning_only + missing_policy: + Missing policy configuration for all address-families. + + Subclass of AvdModel. + allowas_in: Subclass of AvdModel. + ebgp_multihop: Time-to-live in range of hops. + next_hop_self: next_hop_self + link_bandwidth: Subclass of AvdModel. + rib_in_pre_policy_retain: Subclass of AvdModel. + remove_private_as: + Remove private AS numbers in outbound AS path. + + Subclass of AvdModel. + remove_private_as_ingress: Subclass of AvdModel. + session_tracker: session_tracker + shared_secret: Subclass of AvdModel. + ttl_maximum_hops: Maximum number of hops. + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class NeighborInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "remote_as": {"type": str}, + "peer": {"type": str}, + "peer_group": {"type": str, "default": "Peer-group name"}, + "description": {"type": str}, + "peer_filter": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Interface name.""" + remote_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + peer: str | None + """Key only used for documentation or validation purposes.""" + peer_group: str + """Default value: `"Peer-group name"`""" + description: str | None + peer_filter: str | None + """Peer-filter name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + remote_as: str | None | UndefinedType = Undefined, + peer: str | None | UndefinedType = Undefined, + peer_group: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + peer_filter: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: Interface name. + remote_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + peer: Key only used for documentation or validation purposes. + peer_group: peer_group + description: description + peer_filter: Peer-filter name. + _custom_data: _custom_data + + """ + + class NeighborInterfaces(AvdIndexedList[str, NeighborInterfacesItem]): + """Subclass of AvdIndexedList with `NeighborInterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + NeighborInterfaces._item_type = NeighborInterfacesItem + + class AggregateAddressesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "prefix": {"type": str}, + "advertise_only": {"type": bool}, + "as_set": {"type": bool}, + "summary_only": {"type": bool}, + "attribute_map": {"type": str}, + "match_map": {"type": str}, + "_custom_data": {"type": dict}, + } + prefix: str + """IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I".""" + advertise_only: bool | None + as_set: bool | None + summary_only: bool | None + attribute_map: str | None + """Route-map name.""" + match_map: str | None + """Route-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix: str | UndefinedType = Undefined, + advertise_only: bool | None | UndefinedType = Undefined, + as_set: bool | None | UndefinedType = Undefined, + summary_only: bool | None | UndefinedType = Undefined, + attribute_map: str | None | UndefinedType = Undefined, + match_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AggregateAddressesItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I". + advertise_only: advertise_only + as_set: as_set + summary_only: summary_only + attribute_map: Route-map name. + match_map: Route-map name. + _custom_data: _custom_data + + """ + + class AggregateAddresses(AvdIndexedList[str, AggregateAddressesItem]): + """Subclass of AvdIndexedList with `AggregateAddressesItem` items. Primary key is `prefix` (`str`).""" + + _primary_key: ClassVar[str] = "prefix" + + AggregateAddresses._item_type = AggregateAddressesItem + + class Redistribute(AvdModel): + """Subclass of AvdModel.""" + + class AttachedHost(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AttachedHost. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Connected(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Connected. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Dynamic(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "rcf": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dynamic. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + _custom_data: _custom_data + + """ + + class Isis(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "isis_level": {"type": str}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + isis_level: Literal["level-1", "level-2", "level-1-2"] | None + """Redistribute IS-IS route level.""" + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + isis_level: Literal["level-1", "level-2", "level-1-2"] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Isis. + + + Subclass of AvdModel. + + Args: + enabled: enabled + isis_level: Redistribute IS-IS route level. + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Ospf(AvdModel): + """Subclass of AvdModel.""" + + class MatchExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchInternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchInternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchNssaExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "nssa_type": {"type": int}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + nssa_type: Literal[1, 2] | None + """NSSA External Type Number.""" + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + nssa_type: Literal[1, 2] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchNssaExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + nssa_type: NSSA External Type Number. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "match_external": {"type": MatchExternal}, + "match_internal": {"type": MatchInternal}, + "match_nssa_external": {"type": MatchNssaExternal}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Redistribute OSPF routes.""" + match_external: MatchExternal + """ + Redistribute OSPF routes learned from external sources. + + Subclass of AvdModel. + """ + match_internal: MatchInternal + """ + Redistribute OSPF routes learned from internal sources. + + Subclass of AvdModel. + """ + match_nssa_external: MatchNssaExternal + """ + Redistribute OSPF routes learned from external NSSA sources. + + Subclass of AvdModel. + """ + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + match_external: MatchExternal | UndefinedType = Undefined, + match_internal: MatchInternal | UndefinedType = Undefined, + match_nssa_external: MatchNssaExternal | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospf. + + + Subclass of AvdModel. + + Args: + enabled: Redistribute OSPF routes. + match_external: + Redistribute OSPF routes learned from external sources. + + Subclass of AvdModel. + match_internal: + Redistribute OSPF routes learned from internal sources. + + Subclass of AvdModel. + match_nssa_external: + Redistribute OSPF routes learned from external NSSA sources. + + Subclass of AvdModel. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Ospfv3(AvdModel): + """Subclass of AvdModel.""" + + class MatchExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchInternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchInternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchNssaExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "nssa_type": {"type": int}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + nssa_type: Literal[1, 2] | None + """NSSA External Type Number.""" + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + nssa_type: Literal[1, 2] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchNssaExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + nssa_type: NSSA External Type Number. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "match_external": {"type": MatchExternal}, + "match_internal": {"type": MatchInternal}, + "match_nssa_external": {"type": MatchNssaExternal}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Redistribute OSPFv3 routes.""" + match_external: MatchExternal + """ + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + """ + match_internal: MatchInternal + """ + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + """ + match_nssa_external: MatchNssaExternal + """ + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + """ + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + match_external: MatchExternal | UndefinedType = Undefined, + match_internal: MatchInternal | UndefinedType = Undefined, + match_nssa_external: MatchNssaExternal | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospfv3. + + + Subclass of AvdModel. + + Args: + enabled: Redistribute OSPFv3 routes. + match_external: + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + match_internal: + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + match_nssa_external: + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Rip(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Rip. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Static(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Static. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class User(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "rcf": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + User. + + + Subclass of AvdModel. + + Args: + enabled: enabled + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "attached_host": {"type": AttachedHost}, + "bgp": {"type": Bgp}, + "connected": {"type": Connected}, + "dynamic": {"type": Dynamic}, + "isis": {"type": Isis}, + "ospf": {"type": Ospf}, + "ospfv3": {"type": Ospfv3}, + "rip": {"type": Rip}, + "static": {"type": Static}, + "user": {"type": User}, + "_custom_data": {"type": dict}, + } + attached_host: AttachedHost + """Subclass of AvdModel.""" + bgp: Bgp + """Subclass of AvdModel.""" + connected: Connected + """Subclass of AvdModel.""" + dynamic: Dynamic + """Subclass of AvdModel.""" + isis: Isis + """Subclass of AvdModel.""" + ospf: Ospf + """Subclass of AvdModel.""" + ospfv3: Ospfv3 + """Subclass of AvdModel.""" + rip: Rip + """Subclass of AvdModel.""" + static: Static + """Subclass of AvdModel.""" + user: User + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + attached_host: AttachedHost | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + connected: Connected | UndefinedType = Undefined, + dynamic: Dynamic | UndefinedType = Undefined, + isis: Isis | UndefinedType = Undefined, + ospf: Ospf | UndefinedType = Undefined, + ospfv3: Ospfv3 | UndefinedType = Undefined, + rip: Rip | UndefinedType = Undefined, + static: Static | UndefinedType = Undefined, + user: User | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Redistribute. + + + Subclass of AvdModel. + + Args: + attached_host: Subclass of AvdModel. + bgp: Subclass of AvdModel. + connected: Subclass of AvdModel. + dynamic: Subclass of AvdModel. + isis: Subclass of AvdModel. + ospf: Subclass of AvdModel. + ospfv3: Subclass of AvdModel. + rip: Subclass of AvdModel. + static: Subclass of AvdModel. + user: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class RedistributeRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "source_protocol": {"type": str}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "ospf_route_type": {"type": str}, + "_custom_data": {"type": dict}, + } + source_protocol: Literal["attached-host", "bgp", "connected", "dynamic", "isis", "ospf", "ospfv3", "rip", "static", "user"] + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only applicable if `source_protocol` is one of `connected`, + `static`, `isis`, `user`, `dynamic`. + """ + include_leaked: bool | None + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None + """ + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospf' and + 'ospfv3'. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source_protocol: Literal["attached-host", "bgp", "connected", "dynamic", "isis", "ospf", "ospfv3", "rip", "static", "user"] + | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RedistributeRoutesItem. + + + Subclass of AvdModel. + + Args: + source_protocol: source_protocol + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only applicable if `source_protocol` is one of `connected`, + `static`, `isis`, `user`, `dynamic`. + include_leaked: include_leaked + ospf_route_type: + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospf' and + 'ospfv3'. + _custom_data: _custom_data + + """ + + class RedistributeRoutes(AvdList[RedistributeRoutesItem]): + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + + RedistributeRoutes._item_type = RedistributeRoutesItem + + class VlanAwareBundlesItem(AvdModel): + """Subclass of AvdModel.""" + + class RdEvpnDomain(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"domain": {"type": str}, "rd": {"type": str}, "_custom_data": {"type": dict}} + domain: Literal["remote", "all"] | None + rd: str | None + """Route distinguisher.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + domain: Literal["remote", "all"] | None | UndefinedType = Undefined, + rd: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RdEvpnDomain. + + + Subclass of AvdModel. + + Args: + domain: domain + rd: Route distinguisher. + _custom_data: _custom_data + + """ + + class RouteTargets(AvdModel): + """Subclass of AvdModel.""" + + class Both(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Both._item_type = str + + class Import(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Import._item_type = str + + class Export(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Export._item_type = str + + class ImportEvpnDomainsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"domain": {"type": str}, "route_target": {"type": str}, "_custom_data": {"type": dict}} + domain: Literal["remote", "all"] | None + route_target: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + domain: Literal["remote", "all"] | None | UndefinedType = Undefined, + route_target: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ImportEvpnDomainsItem. + + + Subclass of AvdModel. + + Args: + domain: domain + route_target: route_target + _custom_data: _custom_data + + """ + + class ImportEvpnDomains(AvdList[ImportEvpnDomainsItem]): + """Subclass of AvdList with `ImportEvpnDomainsItem` items.""" + + ImportEvpnDomains._item_type = ImportEvpnDomainsItem + + class ExportEvpnDomainsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"domain": {"type": str}, "route_target": {"type": str}, "_custom_data": {"type": dict}} + domain: Literal["remote", "all"] | None + route_target: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + domain: Literal["remote", "all"] | None | UndefinedType = Undefined, + route_target: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ExportEvpnDomainsItem. + + + Subclass of AvdModel. + + Args: + domain: domain + route_target: route_target + _custom_data: _custom_data + + """ + + class ExportEvpnDomains(AvdList[ExportEvpnDomainsItem]): + """Subclass of AvdList with `ExportEvpnDomainsItem` items.""" + + ExportEvpnDomains._item_type = ExportEvpnDomainsItem + + class ImportExportEvpnDomainsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"domain": {"type": str}, "route_target": {"type": str}, "_custom_data": {"type": dict}} + domain: Literal["remote", "all"] | None + route_target: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + domain: Literal["remote", "all"] | None | UndefinedType = Undefined, + route_target: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ImportExportEvpnDomainsItem. + + + Subclass of AvdModel. + + Args: + domain: domain + route_target: route_target + _custom_data: _custom_data + + """ + + class ImportExportEvpnDomains(AvdList[ImportExportEvpnDomainsItem]): + """Subclass of AvdList with `ImportExportEvpnDomainsItem` items.""" + + ImportExportEvpnDomains._item_type = ImportExportEvpnDomainsItem + + _fields: ClassVar[dict] = { + "both": {"type": Both}, + "field_import": {"type": Import}, + "export": {"type": Export}, + "import_evpn_domains": {"type": ImportEvpnDomains}, + "export_evpn_domains": {"type": ExportEvpnDomains}, + "import_export_evpn_domains": {"type": ImportExportEvpnDomains}, + "_custom_data": {"type": dict}, + } + _field_to_key_map: ClassVar[dict] = {"field_import": "import"} + _key_to_field_map: ClassVar[dict] = {"import": "field_import"} + both: Both + """Subclass of AvdList with `str` items.""" + field_import: Import + """Subclass of AvdList with `str` items.""" + export: Export + """Subclass of AvdList with `str` items.""" + import_evpn_domains: ImportEvpnDomains + """Subclass of AvdList with `ImportEvpnDomainsItem` items.""" + export_evpn_domains: ExportEvpnDomains + """Subclass of AvdList with `ExportEvpnDomainsItem` items.""" + import_export_evpn_domains: ImportExportEvpnDomains + """Subclass of AvdList with `ImportExportEvpnDomainsItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + both: Both | UndefinedType = Undefined, + field_import: Import | UndefinedType = Undefined, + export: Export | UndefinedType = Undefined, + import_evpn_domains: ImportEvpnDomains | UndefinedType = Undefined, + export_evpn_domains: ExportEvpnDomains | UndefinedType = Undefined, + import_export_evpn_domains: ImportExportEvpnDomains | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouteTargets. + + + Subclass of AvdModel. + + Args: + both: Subclass of AvdList with `str` items. + field_import: Subclass of AvdList with `str` items. + export: Subclass of AvdList with `str` items. + import_evpn_domains: Subclass of AvdList with `ImportEvpnDomainsItem` items. + export_evpn_domains: Subclass of AvdList with `ExportEvpnDomainsItem` items. + import_export_evpn_domains: Subclass of AvdList with `ImportExportEvpnDomainsItem` items. + _custom_data: _custom_data + + """ + + class RedistributeRoutes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + RedistributeRoutes._item_type = str + + class NoRedistributeRoutes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + NoRedistributeRoutes._item_type = str + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "tenant": {"type": str}, + "description": {"type": str}, + "rd": {"type": str}, + "rd_evpn_domain": {"type": RdEvpnDomain}, + "route_targets": {"type": RouteTargets}, + "redistribute_routes": {"type": RedistributeRoutes}, + "no_redistribute_routes": {"type": NoRedistributeRoutes}, + "vlan": {"type": str}, + "eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """VLAN aware bundle name.""" + tenant: str | None + """Key only used for documentation or validation purposes.""" + description: str | None + """Key only used for documentation or validation purposes.""" + rd: str | None + """Route distinguisher.""" + rd_evpn_domain: RdEvpnDomain + """Subclass of AvdModel.""" + route_targets: RouteTargets + """Subclass of AvdModel.""" + redistribute_routes: RedistributeRoutes + """Subclass of AvdList with `str` items.""" + no_redistribute_routes: NoRedistributeRoutes + """Subclass of AvdList with `str` items.""" + vlan: str | None + """VLAN range as string. Example "100-200,300".""" + eos_cli: str | None + """ + Multiline EOS CLI rendered directly on the Router BGP, VLAN-aware-bundle definition in the final EOS + configuration. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + tenant: str | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + rd: str | None | UndefinedType = Undefined, + rd_evpn_domain: RdEvpnDomain | UndefinedType = Undefined, + route_targets: RouteTargets | UndefinedType = Undefined, + redistribute_routes: RedistributeRoutes | UndefinedType = Undefined, + no_redistribute_routes: NoRedistributeRoutes | UndefinedType = Undefined, + vlan: str | None | UndefinedType = Undefined, + eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VlanAwareBundlesItem. + + + Subclass of AvdModel. + + Args: + name: VLAN aware bundle name. + tenant: Key only used for documentation or validation purposes. + description: Key only used for documentation or validation purposes. + rd: Route distinguisher. + rd_evpn_domain: Subclass of AvdModel. + route_targets: Subclass of AvdModel. + redistribute_routes: Subclass of AvdList with `str` items. + no_redistribute_routes: Subclass of AvdList with `str` items. + vlan: VLAN range as string. Example "100-200,300". + eos_cli: + Multiline EOS CLI rendered directly on the Router BGP, VLAN-aware-bundle definition in the final EOS + configuration. + _custom_data: _custom_data + + """ + + class VlanAwareBundles(AvdIndexedList[str, VlanAwareBundlesItem]): + """Subclass of AvdIndexedList with `VlanAwareBundlesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + VlanAwareBundles._item_type = VlanAwareBundlesItem + + class VlansItem(AvdModel): + """Subclass of AvdModel.""" + + class RdEvpnDomain(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"domain": {"type": str}, "rd": {"type": str}, "_custom_data": {"type": dict}} + domain: Literal["remote", "all"] | None + rd: str | None + """Route distinguisher.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + domain: Literal["remote", "all"] | None | UndefinedType = Undefined, + rd: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RdEvpnDomain. + + + Subclass of AvdModel. + + Args: + domain: domain + rd: Route distinguisher. + _custom_data: _custom_data + + """ + + class RouteTargets(AvdModel): + """Subclass of AvdModel.""" + + class Both(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Both._item_type = str + + class Import(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Import._item_type = str + + class Export(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Export._item_type = str + + class ImportEvpnDomainsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"domain": {"type": str}, "route_target": {"type": str}, "_custom_data": {"type": dict}} + domain: Literal["remote", "all"] | None + route_target: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + domain: Literal["remote", "all"] | None | UndefinedType = Undefined, + route_target: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ImportEvpnDomainsItem. + + + Subclass of AvdModel. + + Args: + domain: domain + route_target: route_target + _custom_data: _custom_data + + """ + + class ImportEvpnDomains(AvdList[ImportEvpnDomainsItem]): + """Subclass of AvdList with `ImportEvpnDomainsItem` items.""" + + ImportEvpnDomains._item_type = ImportEvpnDomainsItem + + class ExportEvpnDomainsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"domain": {"type": str}, "route_target": {"type": str}, "_custom_data": {"type": dict}} + domain: Literal["remote", "all"] | None + route_target: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + domain: Literal["remote", "all"] | None | UndefinedType = Undefined, + route_target: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ExportEvpnDomainsItem. + + + Subclass of AvdModel. + + Args: + domain: domain + route_target: route_target + _custom_data: _custom_data + + """ + + class ExportEvpnDomains(AvdList[ExportEvpnDomainsItem]): + """Subclass of AvdList with `ExportEvpnDomainsItem` items.""" + + ExportEvpnDomains._item_type = ExportEvpnDomainsItem + + class ImportExportEvpnDomainsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"domain": {"type": str}, "route_target": {"type": str}, "_custom_data": {"type": dict}} + domain: Literal["remote", "all"] | None + route_target: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + domain: Literal["remote", "all"] | None | UndefinedType = Undefined, + route_target: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ImportExportEvpnDomainsItem. + + + Subclass of AvdModel. + + Args: + domain: domain + route_target: route_target + _custom_data: _custom_data + + """ + + class ImportExportEvpnDomains(AvdList[ImportExportEvpnDomainsItem]): + """Subclass of AvdList with `ImportExportEvpnDomainsItem` items.""" + + ImportExportEvpnDomains._item_type = ImportExportEvpnDomainsItem + + _fields: ClassVar[dict] = { + "both": {"type": Both}, + "field_import": {"type": Import}, + "export": {"type": Export}, + "import_evpn_domains": {"type": ImportEvpnDomains}, + "export_evpn_domains": {"type": ExportEvpnDomains}, + "import_export_evpn_domains": {"type": ImportExportEvpnDomains}, + "_custom_data": {"type": dict}, + } + _field_to_key_map: ClassVar[dict] = {"field_import": "import"} + _key_to_field_map: ClassVar[dict] = {"import": "field_import"} + both: Both + """Subclass of AvdList with `str` items.""" + field_import: Import + """Subclass of AvdList with `str` items.""" + export: Export + """Subclass of AvdList with `str` items.""" + import_evpn_domains: ImportEvpnDomains + """Subclass of AvdList with `ImportEvpnDomainsItem` items.""" + export_evpn_domains: ExportEvpnDomains + """Subclass of AvdList with `ExportEvpnDomainsItem` items.""" + import_export_evpn_domains: ImportExportEvpnDomains + """Subclass of AvdList with `ImportExportEvpnDomainsItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + both: Both | UndefinedType = Undefined, + field_import: Import | UndefinedType = Undefined, + export: Export | UndefinedType = Undefined, + import_evpn_domains: ImportEvpnDomains | UndefinedType = Undefined, + export_evpn_domains: ExportEvpnDomains | UndefinedType = Undefined, + import_export_evpn_domains: ImportExportEvpnDomains | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouteTargets. + + + Subclass of AvdModel. + + Args: + both: Subclass of AvdList with `str` items. + field_import: Subclass of AvdList with `str` items. + export: Subclass of AvdList with `str` items. + import_evpn_domains: Subclass of AvdList with `ImportEvpnDomainsItem` items. + export_evpn_domains: Subclass of AvdList with `ExportEvpnDomainsItem` items. + import_export_evpn_domains: Subclass of AvdList with `ImportExportEvpnDomainsItem` items. + _custom_data: _custom_data + + """ + + class RedistributeRoutes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + RedistributeRoutes._item_type = str + + class NoRedistributeRoutes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + NoRedistributeRoutes._item_type = str + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "tenant": {"type": str}, + "rd": {"type": str}, + "rd_evpn_domain": {"type": RdEvpnDomain}, + "route_targets": {"type": RouteTargets}, + "redistribute_routes": {"type": RedistributeRoutes}, + "no_redistribute_routes": {"type": NoRedistributeRoutes}, + "eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + id: int + tenant: str | None + """Key only used for documentation or validation purposes.""" + rd: str | None + """Route distinguisher.""" + rd_evpn_domain: RdEvpnDomain + """Subclass of AvdModel.""" + route_targets: RouteTargets + """Subclass of AvdModel.""" + redistribute_routes: RedistributeRoutes + """Subclass of AvdList with `str` items.""" + no_redistribute_routes: NoRedistributeRoutes + """Subclass of AvdList with `str` items.""" + eos_cli: str | None + """ + Multiline EOS CLI rendered directly on the Router BGP, VLAN definition in the final EOS + configuration. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + tenant: str | None | UndefinedType = Undefined, + rd: str | None | UndefinedType = Undefined, + rd_evpn_domain: RdEvpnDomain | UndefinedType = Undefined, + route_targets: RouteTargets | UndefinedType = Undefined, + redistribute_routes: RedistributeRoutes | UndefinedType = Undefined, + no_redistribute_routes: NoRedistributeRoutes | UndefinedType = Undefined, + eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VlansItem. + + + Subclass of AvdModel. + + Args: + id: id + tenant: Key only used for documentation or validation purposes. + rd: Route distinguisher. + rd_evpn_domain: Subclass of AvdModel. + route_targets: Subclass of AvdModel. + redistribute_routes: Subclass of AvdList with `str` items. + no_redistribute_routes: Subclass of AvdList with `str` items. + eos_cli: + Multiline EOS CLI rendered directly on the Router BGP, VLAN definition in the final EOS + configuration. + _custom_data: _custom_data + + """ + + class Vlans(AvdIndexedList[int, VlansItem]): + """Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + Vlans._item_type = VlansItem + + class VpwsItem(AvdModel): + """Subclass of AvdModel.""" + + class RouteTargets(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"import_export": {"type": str}, "_custom_data": {"type": dict}} + import_export: str | None + """Route Target.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, import_export: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + RouteTargets. + + + Subclass of AvdModel. + + Args: + import_export: Route Target. + _custom_data: _custom_data + + """ + + class PseudowiresItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "id_local": {"type": int}, "id_remote": {"type": int}, "_custom_data": {"type": dict}} + name: str + """Pseudowire name.""" + id_local: int | None + """Must match id_remote on other pe.""" + id_remote: int | None + """Must match id_local on other pe.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + id_local: int | None | UndefinedType = Undefined, + id_remote: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PseudowiresItem. + + + Subclass of AvdModel. + + Args: + name: Pseudowire name. + id_local: Must match id_remote on other pe. + id_remote: Must match id_local on other pe. + _custom_data: _custom_data + + """ + + class Pseudowires(AvdIndexedList[str, PseudowiresItem]): + """Subclass of AvdIndexedList with `PseudowiresItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Pseudowires._item_type = PseudowiresItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "rd": {"type": str}, + "route_targets": {"type": RouteTargets}, + "mpls_control_word": {"type": bool}, + "label_flow": {"type": bool}, + "mtu": {"type": int}, + "pseudowires": {"type": Pseudowires}, + "_custom_data": {"type": dict}, + } + name: str + """VPWS instance name.""" + rd: str | None + """Route distinguisher.""" + route_targets: RouteTargets + """Subclass of AvdModel.""" + mpls_control_word: bool | None + label_flow: bool | None + mtu: int | None + pseudowires: Pseudowires + """Subclass of AvdIndexedList with `PseudowiresItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + rd: str | None | UndefinedType = Undefined, + route_targets: RouteTargets | UndefinedType = Undefined, + mpls_control_word: bool | None | UndefinedType = Undefined, + label_flow: bool | None | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + pseudowires: Pseudowires | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VpwsItem. + + + Subclass of AvdModel. + + Args: + name: VPWS instance name. + rd: Route distinguisher. + route_targets: Subclass of AvdModel. + mpls_control_word: mpls_control_word + label_flow: label_flow + mtu: mtu + pseudowires: Subclass of AvdIndexedList with `PseudowiresItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class Vpws(AvdIndexedList[str, VpwsItem]): + """Subclass of AvdIndexedList with `VpwsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vpws._item_type = VpwsItem + + class AddressFamilyEvpn(AvdModel): + """Subclass of AvdModel.""" + + class NeighborDefault(AvdModel): + """Subclass of AvdModel.""" + + class NextHopSelfReceivedEvpnRoutes(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enable": {"type": bool}, "inter_domain": {"type": bool}, "_custom_data": {"type": dict}} + enable: bool | None + inter_domain: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enable: bool | None | UndefinedType = Undefined, + inter_domain: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NextHopSelfReceivedEvpnRoutes. + + + Subclass of AvdModel. + + Args: + enable: enable + inter_domain: inter_domain + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "encapsulation": {"type": str}, + "next_hop_self_source_interface": {"type": str}, + "next_hop_self_received_evpn_routes": {"type": NextHopSelfReceivedEvpnRoutes}, + "_custom_data": {"type": dict}, + } + encapsulation: Literal["vxlan", "mpls", "path-selection"] | None + """Transport encapsulation for neighbor.""" + next_hop_self_source_interface: str | None + """Source interface name for MPLS encapsulation. Requires `encapsulation` to be set as `mpls`.""" + next_hop_self_received_evpn_routes: NextHopSelfReceivedEvpnRoutes + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + encapsulation: Literal["vxlan", "mpls", "path-selection"] | None | UndefinedType = Undefined, + next_hop_self_source_interface: str | None | UndefinedType = Undefined, + next_hop_self_received_evpn_routes: NextHopSelfReceivedEvpnRoutes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborDefault. + + + Subclass of AvdModel. + + Args: + encapsulation: Transport encapsulation for neighbor. + next_hop_self_source_interface: Source interface name for MPLS encapsulation. Requires `encapsulation` to be set as `mpls`. + next_hop_self_received_evpn_routes: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class NextHopMplsResolutionRibsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"rib_type": {"type": str}, "rib_name": {"type": str}, "_custom_data": {"type": dict}} + rib_type: Literal["system-connected", "tunnel-rib-colored", "tunnel-rib"] + """Type of RIB. For 'tunnel-rib', use 'rib_name' to specify the name of the Tunnel-RIB to use.""" + rib_name: str | None + """The name of the tunnel-rib to use when using 'tunnel-rib' type.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + rib_type: Literal["system-connected", "tunnel-rib-colored", "tunnel-rib"] | UndefinedType = Undefined, + rib_name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NextHopMplsResolutionRibsItem. + + + Subclass of AvdModel. + + Args: + rib_type: Type of RIB. For 'tunnel-rib', use 'rib_name' to specify the name of the Tunnel-RIB to use. + rib_name: The name of the tunnel-rib to use when using 'tunnel-rib' type. + _custom_data: _custom_data + + """ + + class NextHopMplsResolutionRibs(AvdList[NextHopMplsResolutionRibsItem]): + """Subclass of AvdList with `NextHopMplsResolutionRibsItem` items.""" + + NextHopMplsResolutionRibs._item_type = NextHopMplsResolutionRibsItem + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + class DefaultRoute(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "rcf": {"type": str}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultRoute. + + + Subclass of AvdModel. + + Args: + enabled: enabled + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + route_map: route_map + _custom_data: _custom_data + + """ + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "send": {"type": str}, "send_limit": {"type": int}, "_custom_data": {"type": dict}} + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "rcf_in": {"type": str}, + "rcf_out": {"type": str}, + "default_route": {"type": DefaultRoute}, + "additional_paths": {"type": AdditionalPaths}, + "encapsulation": {"type": str}, + "next_hop_self_source_interface": {"type": str}, + "_custom_data": {"type": dict}, + } + ip_address: str + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + rcf_in: str | None + """ + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + rcf_out: str | None + """ + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + default_route: DefaultRoute + """Subclass of AvdModel.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + encapsulation: Literal["vxlan", "mpls", "path-selection"] | None + """Transport encapsulation for the neighbor.""" + next_hop_self_source_interface: str | None + """Source interface name for MPLS encapsulation. Requires `encapsulation` to be set as `mpls`.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + rcf_in: str | None | UndefinedType = Undefined, + rcf_out: str | None | UndefinedType = Undefined, + default_route: DefaultRoute | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + encapsulation: Literal["vxlan", "mpls", "path-selection"] | None | UndefinedType = Undefined, + next_hop_self_source_interface: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + rcf_in: + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + rcf_out: + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + default_route: Subclass of AvdModel. + additional_paths: Subclass of AvdModel. + encapsulation: Transport encapsulation for the neighbor. + next_hop_self_source_interface: Source interface name for MPLS encapsulation. Requires `encapsulation` to be set as `mpls`. + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class PeerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class DefaultRoute(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "rcf": {"type": str}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultRoute. + + + Subclass of AvdModel. + + Args: + enabled: enabled + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + route_map: route_map + _custom_data: _custom_data + + """ + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "send": {"type": str}, "send_limit": {"type": int}, "_custom_data": {"type": dict}} + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "rcf_in": {"type": str}, + "rcf_out": {"type": str}, + "default_route": {"type": DefaultRoute}, + "domain_remote": {"type": bool}, + "encapsulation": {"type": str}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + name: str + """Peer-group name.""" + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + rcf_in: str | None + """ + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + rcf_out: str | None + """ + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + default_route: DefaultRoute + """Subclass of AvdModel.""" + domain_remote: bool | None + encapsulation: Literal["vxlan", "mpls", "path-selection"] | None + """Transport encapsulation for the peer-group.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + rcf_in: str | None | UndefinedType = Undefined, + rcf_out: str | None | UndefinedType = Undefined, + default_route: DefaultRoute | UndefinedType = Undefined, + domain_remote: bool | None | UndefinedType = Undefined, + encapsulation: Literal["vxlan", "mpls", "path-selection"] | None | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Peer-group name. + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + rcf_in: + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + rcf_out: + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + default_route: Subclass of AvdModel. + domain_remote: domain_remote + encapsulation: Transport encapsulation for the peer-group. + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PeerGroups(AvdIndexedList[str, PeerGroupsItem]): + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PeerGroups._item_type = PeerGroupsItem + + class EvpnHostflapDetection(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "window": {"type": int}, + "threshold": {"type": int}, + "expiry_timeout": {"type": int}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + window: int | None + """Time (in seconds) to detect a MAC duplication issue.""" + threshold: int | None + """Minimum number of MAC moves that indicate a MAC Duplication issue.""" + expiry_timeout: int | None + """Time (in seconds) to purge a MAC duplication issue.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + window: int | None | UndefinedType = Undefined, + threshold: int | None | UndefinedType = Undefined, + expiry_timeout: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnHostflapDetection. + + + Subclass of AvdModel. + + Args: + enabled: enabled + window: Time (in seconds) to detect a MAC duplication issue. + threshold: Minimum number of MAC moves that indicate a MAC Duplication issue. + expiry_timeout: Time (in seconds) to purge a MAC duplication issue. + _custom_data: _custom_data + + """ + + class NextHop(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"resolution_disabled": {"type": bool}, "_custom_data": {"type": dict}} + resolution_disabled: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, resolution_disabled: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + NextHop. + + + Subclass of AvdModel. + + Args: + resolution_disabled: resolution_disabled + _custom_data: _custom_data + + """ + + class Route(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "import_match_failure_action": {"type": str}, + "import_ethernet_segment_ip_mass_withdraw": {"type": bool}, + "import_overlay_index_gateway": {"type": bool}, + "export_ethernet_segment_ip_mass_withdraw": {"type": bool}, + "_custom_data": {"type": dict}, + } + import_match_failure_action: Literal["discard"] | None + import_ethernet_segment_ip_mass_withdraw: bool | None + import_overlay_index_gateway: bool | None + export_ethernet_segment_ip_mass_withdraw: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + import_match_failure_action: Literal["discard"] | None | UndefinedType = Undefined, + import_ethernet_segment_ip_mass_withdraw: bool | None | UndefinedType = Undefined, + import_overlay_index_gateway: bool | None | UndefinedType = Undefined, + export_ethernet_segment_ip_mass_withdraw: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Route. + + + Subclass of AvdModel. + + Args: + import_match_failure_action: import_match_failure_action + import_ethernet_segment_ip_mass_withdraw: import_ethernet_segment_ip_mass_withdraw + import_overlay_index_gateway: import_overlay_index_gateway + export_ethernet_segment_ip_mass_withdraw: export_ethernet_segment_ip_mass_withdraw + _custom_data: _custom_data + + """ + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "send": {"type": str}, "send_limit": {"type": int}, "_custom_data": {"type": dict}} + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"additional_paths": {"type": AdditionalPaths}, "_custom_data": {"type": dict}} + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, additional_paths: AdditionalPaths | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Layer2FecInPlaceUpdate(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "timeout": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool + timeout: int | None + """In-place FEC update tracking timeout in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + timeout: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Layer2FecInPlaceUpdate. + + + Subclass of AvdModel. + + Args: + enabled: enabled + timeout: In-place FEC update tracking timeout in seconds. + _custom_data: _custom_data + + """ + + class EvpnEthernetSegmentItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "domain": {"type": str}, + "identifier": {"type": str}, + "route_target_import": {"type": str}, + "_custom_data": {"type": dict}, + } + domain: Literal["all", "local", "remote"] + identifier: str | None + """EVPN Ethernet Segment Identifier (Type 1 format).""" + route_target_import: str | None + """Low-order 6 bytes of ES-Import Route Target.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + domain: Literal["all", "local", "remote"] | UndefinedType = Undefined, + identifier: str | None | UndefinedType = Undefined, + route_target_import: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnEthernetSegmentItem. + + + Subclass of AvdModel. + + Args: + domain: domain + identifier: EVPN Ethernet Segment Identifier (Type 1 format). + route_target_import: Low-order 6 bytes of ES-Import Route Target. + _custom_data: _custom_data + + """ + + class EvpnEthernetSegment(AvdIndexedList[str, EvpnEthernetSegmentItem]): + """Subclass of AvdIndexedList with `EvpnEthernetSegmentItem` items. Primary key is `domain` (`str`).""" + + _primary_key: ClassVar[str] = "domain" + + EvpnEthernetSegment._item_type = EvpnEthernetSegmentItem + + class BgpAdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + class Send(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "any": {"type": bool}, + "backup": {"type": bool}, + "ecmp": {"type": bool}, + "ecmp_limit": {"type": int}, + "limit": {"type": int}, + "_custom_data": {"type": dict}, + } + any: bool | None + """Any eligible path.""" + backup: bool | None + """Best path and installed backup path.""" + ecmp: bool | None + """All paths in best path ECMP group.""" + ecmp_limit: int | None + """Amount of ECMP paths to send.""" + limit: int | None + """Amount of paths to send.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + any: bool | None | UndefinedType = Undefined, + backup: bool | None | UndefinedType = Undefined, + ecmp: bool | None | UndefinedType = Undefined, + ecmp_limit: int | None | UndefinedType = Undefined, + limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Send. + + + Subclass of AvdModel. + + Args: + any: Any eligible path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + ecmp_limit: Amount of ECMP paths to send. + limit: Amount of paths to send. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "send": {"type": Send}, "_custom_data": {"type": dict}} + receive: bool | None + """Receive multiple paths.""" + send: Send + """ + Send multiple paths. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + receive: bool | None | UndefinedType = Undefined, + send: Send | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BgpAdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: Receive multiple paths. + send: + Send multiple paths. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "domain_identifier": {"type": str}, + "domain_identifier_remote": {"type": str}, + "neighbor_default": {"type": NeighborDefault}, + "next_hop_mpls_resolution_ribs": {"type": NextHopMplsResolutionRibs}, + "neighbors": {"type": Neighbors}, + "peer_groups": {"type": PeerGroups}, + "evpn_hostflap_detection": {"type": EvpnHostflapDetection}, + "next_hop": {"type": NextHop}, + "route": {"type": Route}, + "next_hop_unchanged": {"type": bool}, + "bgp": {"type": Bgp}, + "layer_2_fec_in_place_update": {"type": Layer2FecInPlaceUpdate}, + "evpn_ethernet_segment": {"type": EvpnEthernetSegment}, + "bgp_additional_paths": {"type": BgpAdditionalPaths}, + "_custom_data": {"type": dict}, + } + domain_identifier: str | None + domain_identifier_remote: str | None + neighbor_default: NeighborDefault + """Subclass of AvdModel.""" + next_hop_mpls_resolution_ribs: NextHopMplsResolutionRibs + """ + Specify the RIBs used to resolve MPLS next-hops. The order of this list determines the order of RIB + lookups. + + Subclass of AvdList with `NextHopMplsResolutionRibsItem` items. + """ + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + peer_groups: PeerGroups + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + evpn_hostflap_detection: EvpnHostflapDetection + """Subclass of AvdModel.""" + next_hop: NextHop + """Subclass of AvdModel.""" + route: Route + """Subclass of AvdModel.""" + next_hop_unchanged: bool | None + bgp: Bgp + """Subclass of AvdModel.""" + layer_2_fec_in_place_update: Layer2FecInPlaceUpdate + """ + BGP layer-2 in-place FEC operation. + + Subclass of AvdModel. + """ + evpn_ethernet_segment: EvpnEthernetSegment + """Subclass of AvdIndexedList with `EvpnEthernetSegmentItem` items. Primary key is `domain` (`str`).""" + bgp_additional_paths: BgpAdditionalPaths + """ + BGP additional-paths commands. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + domain_identifier: str | None | UndefinedType = Undefined, + domain_identifier_remote: str | None | UndefinedType = Undefined, + neighbor_default: NeighborDefault | UndefinedType = Undefined, + next_hop_mpls_resolution_ribs: NextHopMplsResolutionRibs | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + peer_groups: PeerGroups | UndefinedType = Undefined, + evpn_hostflap_detection: EvpnHostflapDetection | UndefinedType = Undefined, + next_hop: NextHop | UndefinedType = Undefined, + route: Route | UndefinedType = Undefined, + next_hop_unchanged: bool | None | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + layer_2_fec_in_place_update: Layer2FecInPlaceUpdate | UndefinedType = Undefined, + evpn_ethernet_segment: EvpnEthernetSegment | UndefinedType = Undefined, + bgp_additional_paths: BgpAdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyEvpn. + + + Subclass of AvdModel. + + Args: + domain_identifier: domain_identifier + domain_identifier_remote: domain_identifier_remote + neighbor_default: Subclass of AvdModel. + next_hop_mpls_resolution_ribs: + Specify the RIBs used to resolve MPLS next-hops. The order of this list determines the order of RIB + lookups. + + Subclass of AvdList with `NextHopMplsResolutionRibsItem` items. + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + peer_groups: Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`). + evpn_hostflap_detection: Subclass of AvdModel. + next_hop: Subclass of AvdModel. + route: Subclass of AvdModel. + next_hop_unchanged: next_hop_unchanged + bgp: Subclass of AvdModel. + layer_2_fec_in_place_update: + BGP layer-2 in-place FEC operation. + + Subclass of AvdModel. + evpn_ethernet_segment: Subclass of AvdIndexedList with `EvpnEthernetSegmentItem` items. Primary key is `domain` (`str`). + bgp_additional_paths: + BGP additional-paths commands. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class AddressFamilyRtc(AvdModel): + """Subclass of AvdModel.""" + + class PeerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class DefaultRouteTarget(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"only": {"type": bool}, "encoding_origin_as_omit": {"type": str}, "_custom_data": {"type": dict}} + only: bool | None + encoding_origin_as_omit: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + only: bool | None | UndefinedType = Undefined, + encoding_origin_as_omit: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultRouteTarget. + + + Subclass of AvdModel. + + Args: + only: only + encoding_origin_as_omit: encoding_origin_as_omit + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "activate": {"type": bool}, + "default_route_target": {"type": DefaultRouteTarget}, + "_custom_data": {"type": dict}, + } + name: str + """Peer-group name.""" + activate: bool | None + default_route_target: DefaultRouteTarget + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + default_route_target: DefaultRouteTarget | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Peer-group name. + activate: activate + default_route_target: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PeerGroups(AvdIndexedList[str, PeerGroupsItem]): + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PeerGroups._item_type = PeerGroupsItem + + _fields: ClassVar[dict] = {"peer_groups": {"type": PeerGroups}, "_custom_data": {"type": dict}} + peer_groups: PeerGroups + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, peer_groups: PeerGroups | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + AddressFamilyRtc. + + + Subclass of AvdModel. + + Args: + peer_groups: Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class AddressFamilyIpv4(AvdModel): + """Subclass of AvdModel.""" + + class NetworksItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + prefix: str + """IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I".""" + route_map: str | None + """Route-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix: str | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NetworksItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I". + route_map: Route-map name. + _custom_data: _custom_data + + """ + + class Networks(AvdIndexedList[str, NetworksItem]): + """Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`).""" + + _primary_key: ClassVar[str] = "prefix" + + Networks._item_type = NetworksItem + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "install": {"type": bool}, + "install_ecmp_primary": {"type": bool}, + "receive": {"type": bool}, + "send": {"type": str}, + "send_limit": {"type": int}, + "_custom_data": {"type": dict}, + } + install: bool | None + """Install BGP backup path.""" + install_ecmp_primary: bool | None + """Allow additional path with ECMP primary path.""" + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + install: bool | None | UndefinedType = Undefined, + install_ecmp_primary: bool | None | UndefinedType = Undefined, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + install: Install BGP backup path. + install_ecmp_primary: Allow additional path with ECMP primary path. + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "additional_paths": {"type": AdditionalPaths}, + "redistribute_internal": {"type": bool}, + "_custom_data": {"type": dict}, + } + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + redistribute_internal: bool | None + """Allow redistribution of iBGP routes into an Interior Gateway Protocol (IGP). EOS default is true.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + redistribute_internal: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + additional_paths: Subclass of AvdModel. + redistribute_internal: Allow redistribution of iBGP routes into an Interior Gateway Protocol (IGP). EOS default is true. + _custom_data: _custom_data + + """ + + class PeerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class DefaultOriginate(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"always": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + always: bool | None + route_map: str | None + """Route-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + always: bool | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultOriginate. + + + Subclass of AvdModel. + + Args: + always: always + route_map: Route-map name. + _custom_data: _custom_data + + """ + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "prefix_list": {"type": str}, + "receive": {"type": bool}, + "send": {"type": str}, + "send_limit": {"type": int}, + "_custom_data": {"type": dict}, + } + prefix_list: str | None + """Apply the configurations only to the routes matching the prefix list.""" + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix_list: str | None | UndefinedType = Undefined, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + prefix_list: Apply the configurations only to the routes matching the prefix list. + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + class NextHop(AvdModel): + """Subclass of AvdModel.""" + + class AddressFamilyIpv6(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "originate": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool + originate: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + originate: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv6. + + + Subclass of AvdModel. + + Args: + enabled: enabled + originate: originate + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"address_family_ipv6": {"type": AddressFamilyIpv6}, "_custom_data": {"type": dict}} + address_family_ipv6: AddressFamilyIpv6 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + address_family_ipv6: AddressFamilyIpv6 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NextHop. + + + Subclass of AvdModel. + + Args: + address_family_ipv6: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "rcf_in": {"type": str}, + "rcf_out": {"type": str}, + "default_originate": {"type": DefaultOriginate}, + "prefix_list_in": {"type": str}, + "prefix_list_out": {"type": str}, + "additional_paths": {"type": AdditionalPaths}, + "next_hop": {"type": NextHop}, + "_custom_data": {"type": dict}, + } + name: str + """Peer-group name.""" + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + rcf_in: str | None + """ + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + rcf_out: str | None + """ + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + default_originate: DefaultOriginate + """Subclass of AvdModel.""" + prefix_list_in: str | None + """Inbound prefix-list name.""" + prefix_list_out: str | None + """Outbound prefix-list name.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + next_hop: NextHop + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + rcf_in: str | None | UndefinedType = Undefined, + rcf_out: str | None | UndefinedType = Undefined, + default_originate: DefaultOriginate | UndefinedType = Undefined, + prefix_list_in: str | None | UndefinedType = Undefined, + prefix_list_out: str | None | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + next_hop: NextHop | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Peer-group name. + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + rcf_in: + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + rcf_out: + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + default_originate: Subclass of AvdModel. + prefix_list_in: Inbound prefix-list name. + prefix_list_out: Outbound prefix-list name. + additional_paths: Subclass of AvdModel. + next_hop: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PeerGroups(AvdIndexedList[str, PeerGroupsItem]): + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PeerGroups._item_type = PeerGroupsItem + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + class DefaultOriginate(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"always": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + always: bool | None + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + always: bool | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultOriginate. + + + Subclass of AvdModel. + + Args: + always: always + route_map: route_map + _custom_data: _custom_data + + """ + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "prefix_list": {"type": str}, + "receive": {"type": bool}, + "send": {"type": str}, + "send_limit": {"type": int}, + "_custom_data": {"type": dict}, + } + prefix_list: str | None + """Apply the configurations only to the routes matching the prefix list.""" + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix_list: str | None | UndefinedType = Undefined, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + prefix_list: Apply the configurations only to the routes matching the prefix list. + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "rcf_in": {"type": str}, + "rcf_out": {"type": str}, + "prefix_list_in": {"type": str}, + "prefix_list_out": {"type": str}, + "default_originate": {"type": DefaultOriginate}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + ip_address: str + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + rcf_in: str | None + """ + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + rcf_out: str | None + """ + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + prefix_list_in: str | None + """Inbound prefix-list name.""" + prefix_list_out: str | None + """Prefix-list name.""" + default_originate: DefaultOriginate + """Subclass of AvdModel.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + rcf_in: str | None | UndefinedType = Undefined, + rcf_out: str | None | UndefinedType = Undefined, + prefix_list_in: str | None | UndefinedType = Undefined, + prefix_list_out: str | None | UndefinedType = Undefined, + default_originate: DefaultOriginate | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + rcf_in: + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + rcf_out: + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + prefix_list_in: Inbound prefix-list name. + prefix_list_out: Prefix-list name. + default_originate: Subclass of AvdModel. + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class Redistribute(AvdModel): + """Subclass of AvdModel.""" + + class AttachedHost(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AttachedHost. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Connected(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Connected. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Dynamic(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "rcf": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dynamic. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + _custom_data: _custom_data + + """ + + class Isis(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "isis_level": {"type": str}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + isis_level: Literal["level-1", "level-2", "level-1-2"] | None + """Redistribute IS-IS route level.""" + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + isis_level: Literal["level-1", "level-2", "level-1-2"] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Isis. + + + Subclass of AvdModel. + + Args: + enabled: enabled + isis_level: Redistribute IS-IS route level. + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Ospf(AvdModel): + """Subclass of AvdModel.""" + + class MatchExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchInternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchInternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchNssaExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "nssa_type": {"type": int}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + nssa_type: Literal[1, 2] | None + """NSSA External Type Number.""" + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + nssa_type: Literal[1, 2] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchNssaExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + nssa_type: NSSA External Type Number. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "match_external": {"type": MatchExternal}, + "match_internal": {"type": MatchInternal}, + "match_nssa_external": {"type": MatchNssaExternal}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Redistribute OSPF routes.""" + match_external: MatchExternal + """ + Redistribute OSPF routes learned from external sources. + + Subclass of AvdModel. + """ + match_internal: MatchInternal + """ + Redistribute OSPF routes learned from internal sources. + + Subclass of AvdModel. + """ + match_nssa_external: MatchNssaExternal + """ + Redistribute OSPF routes learned from external NSSA sources. + + Subclass of AvdModel. + """ + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + match_external: MatchExternal | UndefinedType = Undefined, + match_internal: MatchInternal | UndefinedType = Undefined, + match_nssa_external: MatchNssaExternal | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospf. + + + Subclass of AvdModel. + + Args: + enabled: Redistribute OSPF routes. + match_external: + Redistribute OSPF routes learned from external sources. + + Subclass of AvdModel. + match_internal: + Redistribute OSPF routes learned from internal sources. + + Subclass of AvdModel. + match_nssa_external: + Redistribute OSPF routes learned from external NSSA sources. + + Subclass of AvdModel. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Ospfv3(AvdModel): + """Subclass of AvdModel.""" + + class MatchExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchInternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchInternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchNssaExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "nssa_type": {"type": int}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + nssa_type: Literal[1, 2] | None + """NSSA External Type Number.""" + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + nssa_type: Literal[1, 2] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchNssaExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + nssa_type: NSSA External Type Number. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "match_external": {"type": MatchExternal}, + "match_internal": {"type": MatchInternal}, + "match_nssa_external": {"type": MatchNssaExternal}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Redistribute OSPFv3 routes.""" + match_external: MatchExternal + """ + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + """ + match_internal: MatchInternal + """ + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + """ + match_nssa_external: MatchNssaExternal + """ + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + """ + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + match_external: MatchExternal | UndefinedType = Undefined, + match_internal: MatchInternal | UndefinedType = Undefined, + match_nssa_external: MatchNssaExternal | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospfv3. + + + Subclass of AvdModel. + + Args: + enabled: Redistribute OSPFv3 routes. + match_external: + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + match_internal: + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + match_nssa_external: + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Rip(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Rip. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Static(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Static. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class User(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "rcf": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + User. + + + Subclass of AvdModel. + + Args: + enabled: enabled + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "attached_host": {"type": AttachedHost}, + "bgp": {"type": Bgp}, + "connected": {"type": Connected}, + "dynamic": {"type": Dynamic}, + "isis": {"type": Isis}, + "ospf": {"type": Ospf}, + "ospfv3": {"type": Ospfv3}, + "rip": {"type": Rip}, + "static": {"type": Static}, + "user": {"type": User}, + "_custom_data": {"type": dict}, + } + attached_host: AttachedHost + """Subclass of AvdModel.""" + bgp: Bgp + """Subclass of AvdModel.""" + connected: Connected + """Subclass of AvdModel.""" + dynamic: Dynamic + """Subclass of AvdModel.""" + isis: Isis + """Subclass of AvdModel.""" + ospf: Ospf + """Subclass of AvdModel.""" + ospfv3: Ospfv3 + """Subclass of AvdModel.""" + rip: Rip + """Subclass of AvdModel.""" + static: Static + """Subclass of AvdModel.""" + user: User + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + attached_host: AttachedHost | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + connected: Connected | UndefinedType = Undefined, + dynamic: Dynamic | UndefinedType = Undefined, + isis: Isis | UndefinedType = Undefined, + ospf: Ospf | UndefinedType = Undefined, + ospfv3: Ospfv3 | UndefinedType = Undefined, + rip: Rip | UndefinedType = Undefined, + static: Static | UndefinedType = Undefined, + user: User | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Redistribute. + + + Subclass of AvdModel. + + Args: + attached_host: Subclass of AvdModel. + bgp: Subclass of AvdModel. + connected: Subclass of AvdModel. + dynamic: Subclass of AvdModel. + isis: Subclass of AvdModel. + ospf: Subclass of AvdModel. + ospfv3: Subclass of AvdModel. + rip: Subclass of AvdModel. + static: Subclass of AvdModel. + user: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class RedistributeRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "source_protocol": {"type": str}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "rcf": {"type": str}, + "ospf_route_type": {"type": str}, + "_custom_data": {"type": dict}, + } + source_protocol: Literal["attached-host", "bgp", "connected", "dynamic", "isis", "ospf", "ospfv3", "rip", "static", "user"] + route_map: str | None + include_leaked: bool | None + """Only applicable if `source_protocol` is one of `connected`, `static`, `isis`, `ospf`, `ospfv3`.""" + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only applicable if `source_protocol` is one of `connected`, + `static`, `isis`, `user`, `dynamic`. + """ + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None + """ + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospf' and + 'ospfv3'. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source_protocol: Literal["attached-host", "bgp", "connected", "dynamic", "isis", "ospf", "ospfv3", "rip", "static", "user"] + | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] + | None + | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RedistributeRoutesItem. + + + Subclass of AvdModel. + + Args: + source_protocol: source_protocol + route_map: route_map + include_leaked: Only applicable if `source_protocol` is one of `connected`, `static`, `isis`, `ospf`, `ospfv3`. + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only applicable if `source_protocol` is one of `connected`, + `static`, `isis`, `user`, `dynamic`. + ospf_route_type: + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospf' and + 'ospfv3'. + _custom_data: _custom_data + + """ + + class RedistributeRoutes(AvdList[RedistributeRoutesItem]): + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + + RedistributeRoutes._item_type = RedistributeRoutesItem + + _fields: ClassVar[dict] = { + "networks": {"type": Networks}, + "bgp": {"type": Bgp}, + "peer_groups": {"type": PeerGroups}, + "neighbors": {"type": Neighbors}, + "redistribute": {"type": Redistribute}, + "redistribute_routes": {"type": RedistributeRoutes}, + "_custom_data": {"type": dict}, + } + networks: Networks + """Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`).""" + bgp: Bgp + """Subclass of AvdModel.""" + peer_groups: PeerGroups + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + redistribute: Redistribute + """ + Redistribute routes in to BGP. + + Subclass of AvdModel. + """ + redistribute_routes: RedistributeRoutes + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + networks: Networks | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + peer_groups: PeerGroups | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + redistribute: Redistribute | UndefinedType = Undefined, + redistribute_routes: RedistributeRoutes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv4. + + + Subclass of AvdModel. + + Args: + networks: Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`). + bgp: Subclass of AvdModel. + peer_groups: Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`). + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + redistribute: + Redistribute routes in to BGP. + + Subclass of AvdModel. + redistribute_routes: Subclass of AvdList with `RedistributeRoutesItem` items. + _custom_data: _custom_data + + """ + + class AddressFamilyIpv4LabeledUnicast(AvdModel): + """Subclass of AvdModel.""" + + class AigpSession(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"confederation": {"type": bool}, "ebgp": {"type": bool}, "ibgp": {"type": bool}, "_custom_data": {"type": dict}} + confederation: bool | None + ebgp: bool | None + ibgp: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + confederation: bool | None | UndefinedType = Undefined, + ebgp: bool | None | UndefinedType = Undefined, + ibgp: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AigpSession. + + + Subclass of AvdModel. + + Args: + confederation: confederation + ebgp: ebgp + ibgp: ibgp + _custom_data: _custom_data + + """ + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "send": {"type": str}, "send_limit": {"type": int}, "_custom_data": {"type": dict}} + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + class DirectionIn(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "action": {"type": str}, + "include_community_list": {"type": bool}, + "include_prefix_list": {"type": bool}, + "include_sub_route_map": {"type": bool}, + "_custom_data": {"type": dict}, + } + action: Literal["deny", "permit", "deny-in-out"] + """Missing policy action.""" + include_community_list: bool | None + """Include community-list references in missing policy decision.""" + include_prefix_list: bool | None + """Include prefix-list references in missing policy decision.""" + include_sub_route_map: bool | None + """Include sub-route-map references in missing policy decision.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["deny", "permit", "deny-in-out"] | UndefinedType = Undefined, + include_community_list: bool | None | UndefinedType = Undefined, + include_prefix_list: bool | None | UndefinedType = Undefined, + include_sub_route_map: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionIn. + + + Subclass of AvdModel. + + Args: + action: Missing policy action. + include_community_list: Include community-list references in missing policy decision. + include_prefix_list: Include prefix-list references in missing policy decision. + include_sub_route_map: Include sub-route-map references in missing policy decision. + _custom_data: _custom_data + + """ + + class DirectionOut(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "action": {"type": str}, + "include_community_list": {"type": bool}, + "include_prefix_list": {"type": bool}, + "include_sub_route_map": {"type": bool}, + "_custom_data": {"type": dict}, + } + action: Literal["deny", "permit", "deny-in-out"] + """Missing policy action.""" + include_community_list: bool | None + """Include community-list references in missing policy decision.""" + include_prefix_list: bool | None + """Include prefix-list references in missing policy decision.""" + include_sub_route_map: bool | None + """Include sub-route-map references in missing policy decision.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["deny", "permit", "deny-in-out"] | UndefinedType = Undefined, + include_community_list: bool | None | UndefinedType = Undefined, + include_prefix_list: bool | None | UndefinedType = Undefined, + include_sub_route_map: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionOut. + + + Subclass of AvdModel. + + Args: + action: Missing policy action. + include_community_list: Include community-list references in missing policy decision. + include_prefix_list: Include prefix-list references in missing policy decision. + include_sub_route_map: Include sub-route-map references in missing policy decision. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"direction_in": {"type": DirectionIn}, "direction_out": {"type": DirectionOut}, "_custom_data": {"type": dict}} + direction_in: DirectionIn + """ + Missing policy inbound direction. + + Subclass of AvdModel. + """ + direction_out: DirectionOut + """ + Missing policy outbound direction. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in: DirectionIn | UndefinedType = Undefined, + direction_out: DirectionOut | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in: + Missing policy inbound direction. + + Subclass of AvdModel. + direction_out: + Missing policy outbound direction. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "additional_paths": {"type": AdditionalPaths}, + "missing_policy": {"type": MissingPolicy}, + "next_hop_unchanged": {"type": bool}, + "_custom_data": {"type": dict}, + } + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + missing_policy: MissingPolicy + """ + Missing policy configuration for all address-families. + + Subclass of AvdModel. + """ + next_hop_unchanged: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + missing_policy: MissingPolicy | UndefinedType = Undefined, + next_hop_unchanged: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + additional_paths: Subclass of AvdModel. + missing_policy: + Missing policy configuration for all address-families. + + Subclass of AvdModel. + next_hop_unchanged: next_hop_unchanged + _custom_data: _custom_data + + """ + + class NeighborDefault(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"next_hop_self": {"type": bool}, "_custom_data": {"type": dict}} + next_hop_self: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, next_hop_self: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + NeighborDefault. + + + Subclass of AvdModel. + + Args: + next_hop_self: next_hop_self + _custom_data: _custom_data + + """ + + class PeerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "send": {"type": str}, "send_limit": {"type": int}, "_custom_data": {"type": dict}} + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + class GracefulRestartHelper(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"stale_route_map": {"type": str}, "_custom_data": {"type": dict}} + stale_route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, stale_route_map: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + GracefulRestartHelper. + + + Subclass of AvdModel. + + Args: + stale_route_map: stale_route_map + _custom_data: _custom_data + + """ + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + class DirectionIn(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "action": {"type": str}, + "include_community_list": {"type": bool}, + "include_prefix_list": {"type": bool}, + "include_sub_route_map": {"type": bool}, + "_custom_data": {"type": dict}, + } + action: Literal["deny", "permit", "deny-in-out"] + """Missing policy action.""" + include_community_list: bool | None + """Include community-list references in missing policy decision.""" + include_prefix_list: bool | None + """Include prefix-list references in missing policy decision.""" + include_sub_route_map: bool | None + """Include sub-route-map references in missing policy decision.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["deny", "permit", "deny-in-out"] | UndefinedType = Undefined, + include_community_list: bool | None | UndefinedType = Undefined, + include_prefix_list: bool | None | UndefinedType = Undefined, + include_sub_route_map: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionIn. + + + Subclass of AvdModel. + + Args: + action: Missing policy action. + include_community_list: Include community-list references in missing policy decision. + include_prefix_list: Include prefix-list references in missing policy decision. + include_sub_route_map: Include sub-route-map references in missing policy decision. + _custom_data: _custom_data + + """ + + class DirectionOut(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "action": {"type": str}, + "include_community_list": {"type": bool}, + "include_prefix_list": {"type": bool}, + "include_sub_route_map": {"type": bool}, + "_custom_data": {"type": dict}, + } + action: Literal["deny", "permit", "deny-in-out"] + """Missing policy action.""" + include_community_list: bool | None + """Include community-list references in missing policy decision.""" + include_prefix_list: bool | None + """Include prefix-list references in missing policy decision.""" + include_sub_route_map: bool | None + """Include sub-route-map references in missing policy decision.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["deny", "permit", "deny-in-out"] | UndefinedType = Undefined, + include_community_list: bool | None | UndefinedType = Undefined, + include_prefix_list: bool | None | UndefinedType = Undefined, + include_sub_route_map: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionOut. + + + Subclass of AvdModel. + + Args: + action: Missing policy action. + include_community_list: Include community-list references in missing policy decision. + include_prefix_list: Include prefix-list references in missing policy decision. + include_sub_route_map: Include sub-route-map references in missing policy decision. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"direction_in": {"type": DirectionIn}, "direction_out": {"type": DirectionOut}, "_custom_data": {"type": dict}} + direction_in: DirectionIn + """ + Missing policy inbound direction. + + Subclass of AvdModel. + """ + direction_out: DirectionOut + """ + Missing policy outbound direction. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in: DirectionIn | UndefinedType = Undefined, + direction_out: DirectionOut | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in: + Missing policy inbound direction. + + Subclass of AvdModel. + direction_out: + Missing policy outbound direction. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "activate": {"type": bool}, + "additional_paths": {"type": AdditionalPaths}, + "aigp_session": {"type": bool}, + "graceful_restart": {"type": bool}, + "graceful_restart_helper": {"type": GracefulRestartHelper}, + "maximum_advertised_routes": {"type": int}, + "maximum_advertised_routes_warning_limit": {"type": str}, + "missing_policy": {"type": MissingPolicy}, + "multi_path": {"type": bool}, + "next_hop_self": {"type": bool}, + "next_hop_self_source_interface": {"type": str}, + "next_hop_self_v4_mapped_v6_source_interface": {"type": str}, + "next_hop_unchanged": {"type": bool}, + "rcf_in": {"type": str}, + "rcf_out": {"type": str}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Peer-group name.""" + activate: bool | None + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + aigp_session: bool | None + graceful_restart: bool | None + graceful_restart_helper: GracefulRestartHelper + """Subclass of AvdModel.""" + maximum_advertised_routes: int | None + """Maximum number of routes (0 means unlimited).""" + maximum_advertised_routes_warning_limit: str | None + """ + Maximum number of routes after which a warning is issued (0 means never warn) or + Percentage of + maximum number of routes at which to warn ("<1-100> percent"). + """ + missing_policy: MissingPolicy + """ + Missing policy configuration for BGP Labeled-Unicast neighbor. + + Subclass of AvdModel. + """ + multi_path: bool | None + next_hop_self: bool | None + next_hop_self_source_interface: str | None + """Source interface name.""" + next_hop_self_v4_mapped_v6_source_interface: str | None + """v4-mapped-v6 source interface name. Takes precedence over the next_hop_self_source_interface.""" + next_hop_unchanged: bool | None + rcf_in: str | None + """ + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + rcf_out: str | None + """ + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + aigp_session: bool | None | UndefinedType = Undefined, + graceful_restart: bool | None | UndefinedType = Undefined, + graceful_restart_helper: GracefulRestartHelper | UndefinedType = Undefined, + maximum_advertised_routes: int | None | UndefinedType = Undefined, + maximum_advertised_routes_warning_limit: str | None | UndefinedType = Undefined, + missing_policy: MissingPolicy | UndefinedType = Undefined, + multi_path: bool | None | UndefinedType = Undefined, + next_hop_self: bool | None | UndefinedType = Undefined, + next_hop_self_source_interface: str | None | UndefinedType = Undefined, + next_hop_self_v4_mapped_v6_source_interface: str | None | UndefinedType = Undefined, + next_hop_unchanged: bool | None | UndefinedType = Undefined, + rcf_in: str | None | UndefinedType = Undefined, + rcf_out: str | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Peer-group name. + activate: activate + additional_paths: Subclass of AvdModel. + aigp_session: aigp_session + graceful_restart: graceful_restart + graceful_restart_helper: Subclass of AvdModel. + maximum_advertised_routes: Maximum number of routes (0 means unlimited). + maximum_advertised_routes_warning_limit: + Maximum number of routes after which a warning is issued (0 means never warn) or + Percentage of + maximum number of routes at which to warn ("<1-100> percent"). + missing_policy: + Missing policy configuration for BGP Labeled-Unicast neighbor. + + Subclass of AvdModel. + multi_path: multi_path + next_hop_self: next_hop_self + next_hop_self_source_interface: Source interface name. + next_hop_self_v4_mapped_v6_source_interface: v4-mapped-v6 source interface name. Takes precedence over the next_hop_self_source_interface. + next_hop_unchanged: next_hop_unchanged + rcf_in: + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + rcf_out: + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + _custom_data: _custom_data + + """ + + class PeerGroups(AvdIndexedList[str, PeerGroupsItem]): + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PeerGroups._item_type = PeerGroupsItem + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "send": {"type": str}, "send_limit": {"type": int}, "_custom_data": {"type": dict}} + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + class GracefulRestartHelper(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"stale_route_map": {"type": str}, "_custom_data": {"type": dict}} + stale_route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, stale_route_map: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + GracefulRestartHelper. + + + Subclass of AvdModel. + + Args: + stale_route_map: stale_route_map + _custom_data: _custom_data + + """ + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + class DirectionIn(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "action": {"type": str}, + "include_community_list": {"type": bool}, + "include_prefix_list": {"type": bool}, + "include_sub_route_map": {"type": bool}, + "_custom_data": {"type": dict}, + } + action: Literal["deny", "permit", "deny-in-out"] + """Missing policy action.""" + include_community_list: bool | None + """Include community-list references in missing policy decision.""" + include_prefix_list: bool | None + """Include prefix-list references in missing policy decision.""" + include_sub_route_map: bool | None + """Include sub-route-map references in missing policy decision.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["deny", "permit", "deny-in-out"] | UndefinedType = Undefined, + include_community_list: bool | None | UndefinedType = Undefined, + include_prefix_list: bool | None | UndefinedType = Undefined, + include_sub_route_map: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionIn. + + + Subclass of AvdModel. + + Args: + action: Missing policy action. + include_community_list: Include community-list references in missing policy decision. + include_prefix_list: Include prefix-list references in missing policy decision. + include_sub_route_map: Include sub-route-map references in missing policy decision. + _custom_data: _custom_data + + """ + + class DirectionOut(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "action": {"type": str}, + "include_community_list": {"type": bool}, + "include_prefix_list": {"type": bool}, + "include_sub_route_map": {"type": bool}, + "_custom_data": {"type": dict}, + } + action: Literal["deny", "permit", "deny-in-out"] + """Missing policy action.""" + include_community_list: bool | None + """Include community-list references in missing policy decision.""" + include_prefix_list: bool | None + """Include prefix-list references in missing policy decision.""" + include_sub_route_map: bool | None + """Include sub-route-map references in missing policy decision.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["deny", "permit", "deny-in-out"] | UndefinedType = Undefined, + include_community_list: bool | None | UndefinedType = Undefined, + include_prefix_list: bool | None | UndefinedType = Undefined, + include_sub_route_map: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionOut. + + + Subclass of AvdModel. + + Args: + action: Missing policy action. + include_community_list: Include community-list references in missing policy decision. + include_prefix_list: Include prefix-list references in missing policy decision. + include_sub_route_map: Include sub-route-map references in missing policy decision. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"direction_in": {"type": DirectionIn}, "direction_out": {"type": DirectionOut}, "_custom_data": {"type": dict}} + direction_in: DirectionIn + """ + Missing policy inbound direction. + + Subclass of AvdModel. + """ + direction_out: DirectionOut + """ + Missing policy outbound direction. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in: DirectionIn | UndefinedType = Undefined, + direction_out: DirectionOut | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in: + Missing policy inbound direction. + + Subclass of AvdModel. + direction_out: + Missing policy outbound direction. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "activate": {"type": bool}, + "additional_paths": {"type": AdditionalPaths}, + "aigp_session": {"type": bool}, + "graceful_restart": {"type": bool}, + "graceful_restart_helper": {"type": GracefulRestartHelper}, + "maximum_advertised_routes": {"type": int}, + "maximum_advertised_routes_warning_limit": {"type": str}, + "missing_policy": {"type": MissingPolicy}, + "multi_path": {"type": bool}, + "next_hop_self": {"type": bool}, + "next_hop_self_source_interface": {"type": str}, + "next_hop_self_v4_mapped_v6_source_interface": {"type": str}, + "next_hop_unchanged": {"type": bool}, + "rcf_in": {"type": str}, + "rcf_out": {"type": str}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "_custom_data": {"type": dict}, + } + ip_address: str + activate: bool | None + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + aigp_session: bool | None + graceful_restart: bool | None + graceful_restart_helper: GracefulRestartHelper + """Subclass of AvdModel.""" + maximum_advertised_routes: int | None + """Maximum number of routes (0 means unlimited).""" + maximum_advertised_routes_warning_limit: str | None + """ + Maximum number of routes after which a warning is issued (0 means never warn) or + Percentage of + maximum number of routes at which to warn ("<1-100> percent"). + """ + missing_policy: MissingPolicy + """ + Missing policy configuration for BGP Labeled-Unicast neighbor. + + Subclass of AvdModel. + """ + multi_path: bool | None + next_hop_self: bool | None + next_hop_self_source_interface: str | None + """Source interface name.""" + next_hop_self_v4_mapped_v6_source_interface: str | None + """v4-mapped-v6 source interface name. Takes precedence over the next_hop_self_source_interface.""" + next_hop_unchanged: bool | None + rcf_in: str | None + """ + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + rcf_out: str | None + """ + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + aigp_session: bool | None | UndefinedType = Undefined, + graceful_restart: bool | None | UndefinedType = Undefined, + graceful_restart_helper: GracefulRestartHelper | UndefinedType = Undefined, + maximum_advertised_routes: int | None | UndefinedType = Undefined, + maximum_advertised_routes_warning_limit: str | None | UndefinedType = Undefined, + missing_policy: MissingPolicy | UndefinedType = Undefined, + multi_path: bool | None | UndefinedType = Undefined, + next_hop_self: bool | None | UndefinedType = Undefined, + next_hop_self_source_interface: str | None | UndefinedType = Undefined, + next_hop_self_v4_mapped_v6_source_interface: str | None | UndefinedType = Undefined, + next_hop_unchanged: bool | None | UndefinedType = Undefined, + rcf_in: str | None | UndefinedType = Undefined, + rcf_out: str | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + additional_paths: Subclass of AvdModel. + aigp_session: aigp_session + graceful_restart: graceful_restart + graceful_restart_helper: Subclass of AvdModel. + maximum_advertised_routes: Maximum number of routes (0 means unlimited). + maximum_advertised_routes_warning_limit: + Maximum number of routes after which a warning is issued (0 means never warn) or + Percentage of + maximum number of routes at which to warn ("<1-100> percent"). + missing_policy: + Missing policy configuration for BGP Labeled-Unicast neighbor. + + Subclass of AvdModel. + multi_path: multi_path + next_hop_self: next_hop_self + next_hop_self_source_interface: Source interface name. + next_hop_self_v4_mapped_v6_source_interface: v4-mapped-v6 source interface name. Takes precedence over the next_hop_self_source_interface. + next_hop_unchanged: next_hop_unchanged + rcf_in: + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + rcf_out: + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class NetworksItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + prefix: str + """IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I".""" + route_map: str | None + """Route-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix: str | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NetworksItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I". + route_map: Route-map name. + _custom_data: _custom_data + + """ + + class Networks(AvdIndexedList[str, NetworksItem]): + """Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`).""" + + _primary_key: ClassVar[str] = "prefix" + + Networks._item_type = NetworksItem + + class NextHopsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ip_address": {"type": str}, "lfib_backup_ip_forwarding": {"type": bool}, "_custom_data": {"type": dict}} + ip_address: str + lfib_backup_ip_forwarding: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + lfib_backup_ip_forwarding: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NextHopsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + lfib_backup_ip_forwarding: lfib_backup_ip_forwarding + _custom_data: _custom_data + + """ + + class NextHops(AvdIndexedList[str, NextHopsItem]): + """Subclass of AvdIndexedList with `NextHopsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + NextHops._item_type = NextHopsItem + + class NextHopResolutionRibsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"rib_type": {"type": str}, "rib_name": {"type": str}, "_custom_data": {"type": dict}} + rib_type: Literal["system-connected", "tunnel-rib-colored", "tunnel-rib"] + """Type of RIB. For 'tunnel-rib', use 'rib_name' to specify the name of the Tunnel-RIB to use.""" + rib_name: str | None + """The name of the tunnel-rib to use when using 'tunnel-rib' type.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + rib_type: Literal["system-connected", "tunnel-rib-colored", "tunnel-rib"] | UndefinedType = Undefined, + rib_name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NextHopResolutionRibsItem. + + + Subclass of AvdModel. + + Args: + rib_type: Type of RIB. For 'tunnel-rib', use 'rib_name' to specify the name of the Tunnel-RIB to use. + rib_name: The name of the tunnel-rib to use when using 'tunnel-rib' type. + _custom_data: _custom_data + + """ + + class NextHopResolutionRibs(AvdList[NextHopResolutionRibsItem]): + """Subclass of AvdList with `NextHopResolutionRibsItem` items.""" + + NextHopResolutionRibs._item_type = NextHopResolutionRibsItem + + class TunnelSourceProtocolsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"protocol": {"type": str}, "rcf": {"type": str}, "_custom_data": {"type": dict}} + protocol: Literal["isis segment-routing", "ldp"] + rcf: str | None + """ + Optional RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + protocol: Literal["isis segment-routing", "ldp"] | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TunnelSourceProtocolsItem. + + + Subclass of AvdModel. + + Args: + protocol: protocol + rcf: + Optional RCF function name with parenthesis. + Example: MyFunction(myarg). + _custom_data: _custom_data + + """ + + class TunnelSourceProtocols(AvdIndexedList[str, TunnelSourceProtocolsItem]): + """ + Subclass of AvdIndexedList with `TunnelSourceProtocolsItem` items. Primary key is `protocol` + (`str`). + """ + + _primary_key: ClassVar[str] = "protocol" + + TunnelSourceProtocols._item_type = TunnelSourceProtocolsItem + + _fields: ClassVar[dict] = { + "aigp_session": {"type": AigpSession}, + "bgp": {"type": Bgp}, + "graceful_restart": {"type": bool}, + "label_local_termination": {"type": str}, + "lfib_entry_installation_skipped": {"type": bool}, + "neighbor_default": {"type": NeighborDefault}, + "peer_groups": {"type": PeerGroups}, + "neighbors": {"type": Neighbors}, + "networks": {"type": Networks}, + "next_hops": {"type": NextHops}, + "next_hop_resolution_ribs": {"type": NextHopResolutionRibs}, + "tunnel_source_protocols": {"type": TunnelSourceProtocols}, + "update_wait_for_convergence": {"type": bool}, + "_custom_data": {"type": dict}, + } + aigp_session: AigpSession + """Subclass of AvdModel.""" + bgp: Bgp + """Subclass of AvdModel.""" + graceful_restart: bool | None + label_local_termination: Literal["explicit-null", "implicit-null"] | None + lfib_entry_installation_skipped: bool | None + """Skip LFIB entry installation and next hop self route advertisements.""" + neighbor_default: NeighborDefault + """Subclass of AvdModel.""" + peer_groups: PeerGroups + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + networks: Networks + """Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`).""" + next_hops: NextHops + """Subclass of AvdIndexedList with `NextHopsItem` items. Primary key is `ip_address` (`str`).""" + next_hop_resolution_ribs: NextHopResolutionRibs + """ + Specify the RIBs used to resolve next-hops. The order of this list determines the order of RIB + lookups. + + Subclass of AvdList with `NextHopResolutionRibsItem` items. + """ + tunnel_source_protocols: TunnelSourceProtocols + """ + Subclass of AvdIndexedList with `TunnelSourceProtocolsItem` items. Primary key is `protocol` + (`str`). + """ + update_wait_for_convergence: bool | None + """Wait for BGP to converge before sending out any route updates.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + aigp_session: AigpSession | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + graceful_restart: bool | None | UndefinedType = Undefined, + label_local_termination: Literal["explicit-null", "implicit-null"] | None | UndefinedType = Undefined, + lfib_entry_installation_skipped: bool | None | UndefinedType = Undefined, + neighbor_default: NeighborDefault | UndefinedType = Undefined, + peer_groups: PeerGroups | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + networks: Networks | UndefinedType = Undefined, + next_hops: NextHops | UndefinedType = Undefined, + next_hop_resolution_ribs: NextHopResolutionRibs | UndefinedType = Undefined, + tunnel_source_protocols: TunnelSourceProtocols | UndefinedType = Undefined, + update_wait_for_convergence: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv4LabeledUnicast. + + + Subclass of AvdModel. + + Args: + aigp_session: Subclass of AvdModel. + bgp: Subclass of AvdModel. + graceful_restart: graceful_restart + label_local_termination: label_local_termination + lfib_entry_installation_skipped: Skip LFIB entry installation and next hop self route advertisements. + neighbor_default: Subclass of AvdModel. + peer_groups: Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`). + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + networks: Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`). + next_hops: Subclass of AvdIndexedList with `NextHopsItem` items. Primary key is `ip_address` (`str`). + next_hop_resolution_ribs: + Specify the RIBs used to resolve next-hops. The order of this list determines the order of RIB + lookups. + + Subclass of AvdList with `NextHopResolutionRibsItem` items. + tunnel_source_protocols: + Subclass of AvdIndexedList with `TunnelSourceProtocolsItem` items. Primary key is `protocol` + (`str`). + update_wait_for_convergence: Wait for BGP to converge before sending out any route updates. + _custom_data: _custom_data + + """ + + class AddressFamilyIpv4Multicast(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "_custom_data": {"type": dict}} + receive: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, receive: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: receive + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"additional_paths": {"type": AdditionalPaths}, "_custom_data": {"type": dict}} + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, additional_paths: AdditionalPaths | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PeerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "_custom_data": {"type": dict}} + receive: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, receive: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: receive + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + name: str + """Peer-group name.""" + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Peer-group name. + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PeerGroups(AvdIndexedList[str, PeerGroupsItem]): + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PeerGroups._item_type = PeerGroupsItem + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "_custom_data": {"type": dict}} + receive: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, receive: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: receive + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + ip_address: str + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class Redistribute(AvdModel): + """Subclass of AvdModel.""" + + class AttachedHost(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AttachedHost. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Connected(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Connected. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Isis(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "isis_level": {"type": str}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + isis_level: Literal["level-1", "level-2", "level-1-2"] | None + """Redistribute IS-IS route level.""" + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + isis_level: Literal["level-1", "level-2", "level-1-2"] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Isis. + + + Subclass of AvdModel. + + Args: + enabled: enabled + isis_level: Redistribute IS-IS route level. + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Ospf(AvdModel): + """Subclass of AvdModel.""" + + class MatchExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class MatchInternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchInternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class MatchNssaExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "nssa_type": {"type": int}, + "route_map": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool + nssa_type: Literal[1, 2] | None + """NSSA External Type Number.""" + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + nssa_type: Literal[1, 2] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchNssaExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + nssa_type: NSSA External Type Number. + route_map: route_map + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "match_external": {"type": MatchExternal}, + "match_internal": {"type": MatchInternal}, + "match_nssa_external": {"type": MatchNssaExternal}, + "route_map": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Redistribute OSPF routes.""" + match_external: MatchExternal + """ + Redistribute OSPF routes learned from external sources. + + Subclass of AvdModel. + """ + match_internal: MatchInternal + """ + Redistribute OSPF routes learned from internal sources. + + Subclass of AvdModel. + """ + match_nssa_external: MatchNssaExternal + """ + Redistribute OSPF routes learned from external NSSA sources. + + Subclass of AvdModel. + """ + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + match_external: MatchExternal | UndefinedType = Undefined, + match_internal: MatchInternal | UndefinedType = Undefined, + match_nssa_external: MatchNssaExternal | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospf. + + + Subclass of AvdModel. + + Args: + enabled: Redistribute OSPF routes. + match_external: + Redistribute OSPF routes learned from external sources. + + Subclass of AvdModel. + match_internal: + Redistribute OSPF routes learned from internal sources. + + Subclass of AvdModel. + match_nssa_external: + Redistribute OSPF routes learned from external NSSA sources. + + Subclass of AvdModel. + route_map: route_map + _custom_data: _custom_data + + """ + + class Ospfv3(AvdModel): + """Subclass of AvdModel.""" + + class MatchExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class MatchInternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchInternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class MatchNssaExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "nssa_type": {"type": int}, + "route_map": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool + nssa_type: Literal[1, 2] | None + """NSSA External Type Number.""" + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + nssa_type: Literal[1, 2] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchNssaExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + nssa_type: NSSA External Type Number. + route_map: route_map + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "match_external": {"type": MatchExternal}, + "match_internal": {"type": MatchInternal}, + "match_nssa_external": {"type": MatchNssaExternal}, + "route_map": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Redistribute OSPFv3 routes.""" + match_external: MatchExternal + """ + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + """ + match_internal: MatchInternal + """ + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + """ + match_nssa_external: MatchNssaExternal + """ + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + """ + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + match_external: MatchExternal | UndefinedType = Undefined, + match_internal: MatchInternal | UndefinedType = Undefined, + match_nssa_external: MatchNssaExternal | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospfv3. + + + Subclass of AvdModel. + + Args: + enabled: Redistribute OSPFv3 routes. + match_external: + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + match_internal: + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + match_nssa_external: + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + route_map: route_map + _custom_data: _custom_data + + """ + + class Static(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Static. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "attached_host": {"type": AttachedHost}, + "connected": {"type": Connected}, + "isis": {"type": Isis}, + "ospf": {"type": Ospf}, + "ospfv3": {"type": Ospfv3}, + "static": {"type": Static}, + "_custom_data": {"type": dict}, + } + attached_host: AttachedHost + """Subclass of AvdModel.""" + connected: Connected + """Subclass of AvdModel.""" + isis: Isis + """Subclass of AvdModel.""" + ospf: Ospf + """Subclass of AvdModel.""" + ospfv3: Ospfv3 + """Subclass of AvdModel.""" + static: Static + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + attached_host: AttachedHost | UndefinedType = Undefined, + connected: Connected | UndefinedType = Undefined, + isis: Isis | UndefinedType = Undefined, + ospf: Ospf | UndefinedType = Undefined, + ospfv3: Ospfv3 | UndefinedType = Undefined, + static: Static | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Redistribute. + + + Subclass of AvdModel. + + Args: + attached_host: Subclass of AvdModel. + connected: Subclass of AvdModel. + isis: Subclass of AvdModel. + ospf: Subclass of AvdModel. + ospfv3: Subclass of AvdModel. + static: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class RedistributeRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "source_protocol": {"type": str}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "rcf": {"type": str}, + "ospf_route_type": {"type": str}, + "_custom_data": {"type": dict}, + } + source_protocol: str + route_map: str | None + include_leaked: bool | None + """Only applicable if `source_protocol` is `isis`.""" + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only applicable if `source_protocol` is `isis`. + """ + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None + """ + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospf' and + 'ospfv3'. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source_protocol: str | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] + | None + | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RedistributeRoutesItem. + + + Subclass of AvdModel. + + Args: + source_protocol: source_protocol + route_map: route_map + include_leaked: Only applicable if `source_protocol` is `isis`. + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only applicable if `source_protocol` is `isis`. + ospf_route_type: + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospf' and + 'ospfv3'. + _custom_data: _custom_data + + """ + + class RedistributeRoutes(AvdList[RedistributeRoutesItem]): + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + + RedistributeRoutes._item_type = RedistributeRoutesItem + + _fields: ClassVar[dict] = { + "bgp": {"type": Bgp}, + "peer_groups": {"type": PeerGroups}, + "neighbors": {"type": Neighbors}, + "redistribute": {"type": Redistribute}, + "redistribute_routes": {"type": RedistributeRoutes}, + "_custom_data": {"type": dict}, + } + bgp: Bgp + """Subclass of AvdModel.""" + peer_groups: PeerGroups + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + redistribute: Redistribute + """ + Redistribute routes in to BGP. + + Subclass of AvdModel. + """ + redistribute_routes: RedistributeRoutes + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + bgp: Bgp | UndefinedType = Undefined, + peer_groups: PeerGroups | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + redistribute: Redistribute | UndefinedType = Undefined, + redistribute_routes: RedistributeRoutes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv4Multicast. + + + Subclass of AvdModel. + + Args: + bgp: Subclass of AvdModel. + peer_groups: Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`). + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + redistribute: + Redistribute routes in to BGP. + + Subclass of AvdModel. + redistribute_routes: Subclass of AvdList with `RedistributeRoutesItem` items. + _custom_data: _custom_data + + """ + + class AddressFamilyIpv4SrTe(AvdModel): + """Subclass of AvdModel.""" + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "_custom_data": {"type": dict}, + } + ip_address: str + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class PeerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Peer-group name.""" + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Peer-group name. + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + _custom_data: _custom_data + + """ + + class PeerGroups(AvdIndexedList[str, PeerGroupsItem]): + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PeerGroups._item_type = PeerGroupsItem + + _fields: ClassVar[dict] = {"neighbors": {"type": Neighbors}, "peer_groups": {"type": PeerGroups}, "_custom_data": {"type": dict}} + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + peer_groups: PeerGroups + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + neighbors: Neighbors | UndefinedType = Undefined, + peer_groups: PeerGroups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv4SrTe. + + + Subclass of AvdModel. + + Args: + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + peer_groups: Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class AddressFamilyIpv6(AvdModel): + """Subclass of AvdModel.""" + + class NetworksItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + prefix: str + """IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I".""" + route_map: str | None + """Route-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix: str | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NetworksItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I". + route_map: Route-map name. + _custom_data: _custom_data + + """ + + class Networks(AvdIndexedList[str, NetworksItem]): + """Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`).""" + + _primary_key: ClassVar[str] = "prefix" + + Networks._item_type = NetworksItem + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "install": {"type": bool}, + "install_ecmp_primary": {"type": bool}, + "receive": {"type": bool}, + "send": {"type": str}, + "send_limit": {"type": int}, + "_custom_data": {"type": dict}, + } + install: bool | None + """Install BGP backup path.""" + install_ecmp_primary: bool | None + """Allow additional path with ECMP primary path.""" + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + install: bool | None | UndefinedType = Undefined, + install_ecmp_primary: bool | None | UndefinedType = Undefined, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + install: Install BGP backup path. + install_ecmp_primary: Allow additional path with ECMP primary path. + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "redistribute_internal": {"type": bool}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + redistribute_internal: bool | None + """Allow redistribution of iBGP routes into an Interior Gateway Protocol (IGP). EOS default is true.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + redistribute_internal: bool | None | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + redistribute_internal: Allow redistribution of iBGP routes into an Interior Gateway Protocol (IGP). EOS default is true. + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PeerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "prefix_list": {"type": str}, + "receive": {"type": bool}, + "send": {"type": str}, + "send_limit": {"type": int}, + "_custom_data": {"type": dict}, + } + prefix_list: str | None + """Apply the configurations only to the routes matching the prefix list.""" + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix_list: str | None | UndefinedType = Undefined, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + prefix_list: Apply the configurations only to the routes matching the prefix list. + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "rcf_in": {"type": str}, + "rcf_out": {"type": str}, + "prefix_list_in": {"type": str}, + "prefix_list_out": {"type": str}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + name: str + """Peer-group name.""" + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + rcf_in: str | None + """ + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + rcf_out: str | None + """ + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + prefix_list_in: str | None + """Inbound prefix-list name.""" + prefix_list_out: str | None + """Outbound prefix-list name.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + rcf_in: str | None | UndefinedType = Undefined, + rcf_out: str | None | UndefinedType = Undefined, + prefix_list_in: str | None | UndefinedType = Undefined, + prefix_list_out: str | None | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Peer-group name. + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + rcf_in: + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + rcf_out: + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + prefix_list_in: Inbound prefix-list name. + prefix_list_out: Outbound prefix-list name. + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PeerGroups(AvdIndexedList[str, PeerGroupsItem]): + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PeerGroups._item_type = PeerGroupsItem + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "prefix_list": {"type": str}, + "receive": {"type": bool}, + "send": {"type": str}, + "send_limit": {"type": int}, + "_custom_data": {"type": dict}, + } + prefix_list: str | None + """Apply the configurations only to the routes matching the prefix list.""" + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix_list: str | None | UndefinedType = Undefined, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + prefix_list: Apply the configurations only to the routes matching the prefix list. + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "rcf_in": {"type": str}, + "rcf_out": {"type": str}, + "prefix_list_in": {"type": str}, + "prefix_list_out": {"type": str}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + ip_address: str + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + rcf_in: str | None + """ + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + rcf_out: str | None + """ + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + prefix_list_in: str | None + """Inbound prefix-list name.""" + prefix_list_out: str | None + """Outbound prefix-list name.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + rcf_in: str | None | UndefinedType = Undefined, + rcf_out: str | None | UndefinedType = Undefined, + prefix_list_in: str | None | UndefinedType = Undefined, + prefix_list_out: str | None | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + rcf_in: + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + rcf_out: + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + prefix_list_in: Inbound prefix-list name. + prefix_list_out: Outbound prefix-list name. + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class Redistribute(AvdModel): + """Subclass of AvdModel.""" + + class AttachedHost(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AttachedHost. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Connected(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Connected. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Dhcp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dhcp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Dynamic(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "rcf": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dynamic. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + _custom_data: _custom_data + + """ + + class Isis(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "isis_level": {"type": str}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + isis_level: Literal["level-1", "level-2", "level-1-2"] | None + """Redistribute IS-IS route level.""" + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + isis_level: Literal["level-1", "level-2", "level-1-2"] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Isis. + + + Subclass of AvdModel. + + Args: + enabled: enabled + isis_level: Redistribute IS-IS route level. + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Ospfv3(AvdModel): + """Subclass of AvdModel.""" + + class MatchExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchInternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchInternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchNssaExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "nssa_type": {"type": int}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + nssa_type: Literal[1, 2] | None + """NSSA External Type Number.""" + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + nssa_type: Literal[1, 2] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchNssaExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + nssa_type: NSSA External Type Number. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "match_external": {"type": MatchExternal}, + "match_internal": {"type": MatchInternal}, + "match_nssa_external": {"type": MatchNssaExternal}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Redistribute OSPFv3 routes.""" + match_external: MatchExternal + """ + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + """ + match_internal: MatchInternal + """ + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + """ + match_nssa_external: MatchNssaExternal + """ + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + """ + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + match_external: MatchExternal | UndefinedType = Undefined, + match_internal: MatchInternal | UndefinedType = Undefined, + match_nssa_external: MatchNssaExternal | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospfv3. + + + Subclass of AvdModel. + + Args: + enabled: Redistribute OSPFv3 routes. + match_external: + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + match_internal: + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + match_nssa_external: + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Static(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Static. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class User(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "rcf": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + User. + + + Subclass of AvdModel. + + Args: + enabled: enabled + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "attached_host": {"type": AttachedHost}, + "bgp": {"type": Bgp}, + "connected": {"type": Connected}, + "dhcp": {"type": Dhcp}, + "dynamic": {"type": Dynamic}, + "isis": {"type": Isis}, + "ospfv3": {"type": Ospfv3}, + "static": {"type": Static}, + "user": {"type": User}, + "_custom_data": {"type": dict}, + } + attached_host: AttachedHost + """Subclass of AvdModel.""" + bgp: Bgp + """Subclass of AvdModel.""" + connected: Connected + """Subclass of AvdModel.""" + dhcp: Dhcp + """Subclass of AvdModel.""" + dynamic: Dynamic + """Subclass of AvdModel.""" + isis: Isis + """Subclass of AvdModel.""" + ospfv3: Ospfv3 + """Subclass of AvdModel.""" + static: Static + """Subclass of AvdModel.""" + user: User + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + attached_host: AttachedHost | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + connected: Connected | UndefinedType = Undefined, + dhcp: Dhcp | UndefinedType = Undefined, + dynamic: Dynamic | UndefinedType = Undefined, + isis: Isis | UndefinedType = Undefined, + ospfv3: Ospfv3 | UndefinedType = Undefined, + static: Static | UndefinedType = Undefined, + user: User | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Redistribute. + + + Subclass of AvdModel. + + Args: + attached_host: Subclass of AvdModel. + bgp: Subclass of AvdModel. + connected: Subclass of AvdModel. + dhcp: Subclass of AvdModel. + dynamic: Subclass of AvdModel. + isis: Subclass of AvdModel. + ospfv3: Subclass of AvdModel. + static: Subclass of AvdModel. + user: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class RedistributeRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "source_protocol": {"type": str}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "rcf": {"type": str}, + "ospf_route_type": {"type": str}, + "_custom_data": {"type": dict}, + } + source_protocol: str + route_map: str | None + include_leaked: bool | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only used if `source_protocol` is one of `connected`, + `static`, `isis`, `user`, `dynamic`. + """ + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None + """ + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospfv3'. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source_protocol: str | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] + | None + | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RedistributeRoutesItem. + + + Subclass of AvdModel. + + Args: + source_protocol: source_protocol + route_map: route_map + include_leaked: include_leaked + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only used if `source_protocol` is one of `connected`, + `static`, `isis`, `user`, `dynamic`. + ospf_route_type: + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospfv3'. + _custom_data: _custom_data + + """ + + class RedistributeRoutes(AvdList[RedistributeRoutesItem]): + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + + RedistributeRoutes._item_type = RedistributeRoutesItem + + _fields: ClassVar[dict] = { + "networks": {"type": Networks}, + "bgp": {"type": Bgp}, + "peer_groups": {"type": PeerGroups}, + "neighbors": {"type": Neighbors}, + "redistribute": {"type": Redistribute}, + "redistribute_routes": {"type": RedistributeRoutes}, + "_custom_data": {"type": dict}, + } + networks: Networks + """Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`).""" + bgp: Bgp + """Subclass of AvdModel.""" + peer_groups: PeerGroups + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + redistribute: Redistribute + """ + Redistribute routes in to BGP. + + Subclass of AvdModel. + """ + redistribute_routes: RedistributeRoutes + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + networks: Networks | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + peer_groups: PeerGroups | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + redistribute: Redistribute | UndefinedType = Undefined, + redistribute_routes: RedistributeRoutes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv6. + + + Subclass of AvdModel. + + Args: + networks: Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`). + bgp: Subclass of AvdModel. + peer_groups: Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`). + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + redistribute: + Redistribute routes in to BGP. + + Subclass of AvdModel. + redistribute_routes: Subclass of AvdList with `RedistributeRoutesItem` items. + _custom_data: _custom_data + + """ + + class AddressFamilyIpv6Multicast(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"direction_in_action": {"type": str}, "direction_out_action": {"type": str}, "_custom_data": {"type": dict}} + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in_action: direction_in_action + direction_out_action: direction_out_action + _custom_data: _custom_data + + """ + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "_custom_data": {"type": dict}} + receive: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, receive: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: receive + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "missing_policy": {"type": MissingPolicy}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + missing_policy: MissingPolicy + """Subclass of AvdModel.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + missing_policy: MissingPolicy | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + missing_policy: Subclass of AvdModel. + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "_custom_data": {"type": dict}} + receive: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, receive: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: receive + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + ip_address: str + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class PeerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "_custom_data": {"type": dict}} + receive: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, receive: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: receive + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "activate": {"type": bool}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + name: str + """Peer-group name.""" + activate: bool | None + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Peer-group name. + activate: activate + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PeerGroups(AvdIndexedList[str, PeerGroupsItem]): + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PeerGroups._item_type = PeerGroupsItem + + class NetworksItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + prefix: str + """IPv6 prefix "A:B:C:D:E:F:G:H/I".""" + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix: str | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NetworksItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv6 prefix "A:B:C:D:E:F:G:H/I". + route_map: route_map + _custom_data: _custom_data + + """ + + class Networks(AvdIndexedList[str, NetworksItem]): + """Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`).""" + + _primary_key: ClassVar[str] = "prefix" + + Networks._item_type = NetworksItem + + class Redistribute(AvdModel): + """Subclass of AvdModel.""" + + class Connected(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Connected. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Isis(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "isis_level": {"type": str}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + isis_level: Literal["level-1", "level-2", "level-1-2"] | None + """Redistribute IS-IS route level.""" + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + isis_level: Literal["level-1", "level-2", "level-1-2"] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Isis. + + + Subclass of AvdModel. + + Args: + enabled: enabled + isis_level: Redistribute IS-IS route level. + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Ospf(AvdModel): + """Subclass of AvdModel.""" + + class MatchExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class MatchInternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchInternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class MatchNssaExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "nssa_type": {"type": int}, + "route_map": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool + nssa_type: Literal[1, 2] | None + """NSSA External Type Number.""" + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + nssa_type: Literal[1, 2] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchNssaExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + nssa_type: NSSA External Type Number. + route_map: route_map + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "match_external": {"type": MatchExternal}, + "match_internal": {"type": MatchInternal}, + "match_nssa_external": {"type": MatchNssaExternal}, + "route_map": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Redistribute OSPF routes.""" + match_external: MatchExternal + """ + Redistribute OSPF routes learned from external sources. + + Subclass of AvdModel. + """ + match_internal: MatchInternal + """ + Redistribute OSPF routes learned from internal sources. + + Subclass of AvdModel. + """ + match_nssa_external: MatchNssaExternal + """ + Redistribute OSPF routes learned from external NSSA sources. + + Subclass of AvdModel. + """ + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + match_external: MatchExternal | UndefinedType = Undefined, + match_internal: MatchInternal | UndefinedType = Undefined, + match_nssa_external: MatchNssaExternal | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospf. + + + Subclass of AvdModel. + + Args: + enabled: Redistribute OSPF routes. + match_external: + Redistribute OSPF routes learned from external sources. + + Subclass of AvdModel. + match_internal: + Redistribute OSPF routes learned from internal sources. + + Subclass of AvdModel. + match_nssa_external: + Redistribute OSPF routes learned from external NSSA sources. + + Subclass of AvdModel. + route_map: route_map + _custom_data: _custom_data + + """ + + class Ospfv3(AvdModel): + """Subclass of AvdModel.""" + + class MatchExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class MatchInternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchInternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class MatchNssaExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "nssa_type": {"type": int}, + "route_map": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool + nssa_type: Literal[1, 2] | None + """NSSA External Type Number.""" + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + nssa_type: Literal[1, 2] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchNssaExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + nssa_type: NSSA External Type Number. + route_map: route_map + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "match_external": {"type": MatchExternal}, + "match_internal": {"type": MatchInternal}, + "match_nssa_external": {"type": MatchNssaExternal}, + "route_map": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Redistribute OSPFv3 routes.""" + match_external: MatchExternal + """ + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + """ + match_internal: MatchInternal + """ + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + """ + match_nssa_external: MatchNssaExternal + """ + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + """ + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + match_external: MatchExternal | UndefinedType = Undefined, + match_internal: MatchInternal | UndefinedType = Undefined, + match_nssa_external: MatchNssaExternal | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospfv3. + + + Subclass of AvdModel. + + Args: + enabled: Redistribute OSPFv3 routes. + match_external: + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + match_internal: + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + match_nssa_external: + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + route_map: route_map + _custom_data: _custom_data + + """ + + class Static(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Static. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "connected": {"type": Connected}, + "isis": {"type": Isis}, + "ospf": {"type": Ospf}, + "ospfv3": {"type": Ospfv3}, + "static": {"type": Static}, + "_custom_data": {"type": dict}, + } + connected: Connected + """Subclass of AvdModel.""" + isis: Isis + """Subclass of AvdModel.""" + ospf: Ospf + """Subclass of AvdModel.""" + ospfv3: Ospfv3 + """Subclass of AvdModel.""" + static: Static + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + connected: Connected | UndefinedType = Undefined, + isis: Isis | UndefinedType = Undefined, + ospf: Ospf | UndefinedType = Undefined, + ospfv3: Ospfv3 | UndefinedType = Undefined, + static: Static | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Redistribute. + + + Subclass of AvdModel. + + Args: + connected: Subclass of AvdModel. + isis: Subclass of AvdModel. + ospf: Subclass of AvdModel. + ospfv3: Subclass of AvdModel. + static: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class RedistributeRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "source_protocol": {"type": str}, + "include_leaked": {"type": bool}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "ospf_route_type": {"type": str}, + "_custom_data": {"type": dict}, + } + source_protocol: Literal["connected", "isis", "ospf", "ospfv3", "static"] + include_leaked: bool | None + """Only applicable if `source_protocol` is `isis`.""" + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only applicable if `source_protocol` is `isis`. + """ + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None + """ + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospf' and + 'ospfv3'. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source_protocol: Literal["connected", "isis", "ospf", "ospfv3", "static"] | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] + | None + | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RedistributeRoutesItem. + + + Subclass of AvdModel. + + Args: + source_protocol: source_protocol + include_leaked: Only applicable if `source_protocol` is `isis`. + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only applicable if `source_protocol` is `isis`. + ospf_route_type: + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospf' and + 'ospfv3'. + _custom_data: _custom_data + + """ + + class RedistributeRoutes(AvdList[RedistributeRoutesItem]): + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + + RedistributeRoutes._item_type = RedistributeRoutesItem + + _fields: ClassVar[dict] = { + "bgp": {"type": Bgp}, + "neighbors": {"type": Neighbors}, + "peer_groups": {"type": PeerGroups}, + "networks": {"type": Networks}, + "redistribute": {"type": Redistribute}, + "redistribute_routes": {"type": RedistributeRoutes}, + "_custom_data": {"type": dict}, + } + bgp: Bgp + """Subclass of AvdModel.""" + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + peer_groups: PeerGroups + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + networks: Networks + """Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`).""" + redistribute: Redistribute + """ + Redistribute routes in to BGP. + + Subclass of AvdModel. + """ + redistribute_routes: RedistributeRoutes + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + bgp: Bgp | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + peer_groups: PeerGroups | UndefinedType = Undefined, + networks: Networks | UndefinedType = Undefined, + redistribute: Redistribute | UndefinedType = Undefined, + redistribute_routes: RedistributeRoutes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv6Multicast. + + + Subclass of AvdModel. + + Args: + bgp: Subclass of AvdModel. + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + peer_groups: Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`). + networks: Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`). + redistribute: + Redistribute routes in to BGP. + + Subclass of AvdModel. + redistribute_routes: Subclass of AvdList with `RedistributeRoutesItem` items. + _custom_data: _custom_data + + """ + + class AddressFamilyIpv6SrTe(AvdModel): + """Subclass of AvdModel.""" + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "_custom_data": {"type": dict}, + } + ip_address: str + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class PeerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Peer-group name.""" + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Peer-group name. + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + _custom_data: _custom_data + + """ + + class PeerGroups(AvdIndexedList[str, PeerGroupsItem]): + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PeerGroups._item_type = PeerGroupsItem + + _fields: ClassVar[dict] = {"neighbors": {"type": Neighbors}, "peer_groups": {"type": PeerGroups}, "_custom_data": {"type": dict}} + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + peer_groups: PeerGroups + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + neighbors: Neighbors | UndefinedType = Undefined, + peer_groups: PeerGroups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv6SrTe. + + + Subclass of AvdModel. + + Args: + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + peer_groups: Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class AddressFamilyLinkState(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"direction_in_action": {"type": str}, "direction_out_action": {"type": str}, "_custom_data": {"type": dict}} + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in_action: direction_in_action + direction_out_action: direction_out_action + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"missing_policy": {"type": MissingPolicy}, "_custom_data": {"type": dict}} + missing_policy: MissingPolicy + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, missing_policy: MissingPolicy | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + missing_policy: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PeerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"direction_in_action": {"type": str}, "direction_out_action": {"type": str}, "_custom_data": {"type": dict}} + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in_action: direction_in_action + direction_out_action: direction_out_action + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "activate": {"type": bool}, + "missing_policy": {"type": MissingPolicy}, + "_custom_data": {"type": dict}, + } + name: str + """Peer-group name.""" + activate: bool | None + missing_policy: MissingPolicy + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + missing_policy: MissingPolicy | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Peer-group name. + activate: activate + missing_policy: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PeerGroups(AvdIndexedList[str, PeerGroupsItem]): + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PeerGroups._item_type = PeerGroupsItem + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"direction_in_action": {"type": str}, "direction_out_action": {"type": str}, "_custom_data": {"type": dict}} + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in_action: direction_in_action + direction_out_action: direction_out_action + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "activate": {"type": bool}, + "missing_policy": {"type": MissingPolicy}, + "_custom_data": {"type": dict}, + } + ip_address: str + activate: bool | None + missing_policy: MissingPolicy + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + missing_policy: MissingPolicy | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + missing_policy: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class PathSelection(AvdModel): + """Subclass of AvdModel.""" + + class Roles(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "producer": {"type": bool}, + "consumer": {"type": bool}, + "propagator": {"type": bool}, + "_custom_data": {"type": dict}, + } + producer: bool | None + consumer: bool | None + propagator: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + producer: bool | None | UndefinedType = Undefined, + consumer: bool | None | UndefinedType = Undefined, + propagator: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Roles. + + + Subclass of AvdModel. + + Args: + producer: producer + consumer: consumer + propagator: propagator + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"roles": {"type": Roles}, "_custom_data": {"type": dict}} + roles: Roles + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, roles: Roles | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + PathSelection. + + + Subclass of AvdModel. + + Args: + roles: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "bgp": {"type": Bgp}, + "peer_groups": {"type": PeerGroups}, + "neighbors": {"type": Neighbors}, + "path_selection": {"type": PathSelection}, + "_custom_data": {"type": dict}, + } + bgp: Bgp + """Subclass of AvdModel.""" + peer_groups: PeerGroups + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + path_selection: PathSelection + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + bgp: Bgp | UndefinedType = Undefined, + peer_groups: PeerGroups | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + path_selection: PathSelection | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyLinkState. + + + Subclass of AvdModel. + + Args: + bgp: Subclass of AvdModel. + peer_groups: Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`). + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + path_selection: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class AddressFamilyFlowSpecIpv4(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"direction_in_action": {"type": str}, "direction_out_action": {"type": str}, "_custom_data": {"type": dict}} + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in_action: direction_in_action + direction_out_action: direction_out_action + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"missing_policy": {"type": MissingPolicy}, "_custom_data": {"type": dict}} + missing_policy: MissingPolicy + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, missing_policy: MissingPolicy | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + missing_policy: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ip_address": {"type": str}, "activate": {"type": bool}, "_custom_data": {"type": dict}} + ip_address: str + activate: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class PeerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "activate": {"type": bool}, "_custom_data": {"type": dict}} + name: str + """Peer-group name.""" + activate: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Peer-group name. + activate: activate + _custom_data: _custom_data + + """ + + class PeerGroups(AvdIndexedList[str, PeerGroupsItem]): + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PeerGroups._item_type = PeerGroupsItem + + _fields: ClassVar[dict] = { + "bgp": {"type": Bgp}, + "neighbors": {"type": Neighbors}, + "peer_groups": {"type": PeerGroups}, + "_custom_data": {"type": dict}, + } + bgp: Bgp + """Subclass of AvdModel.""" + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + peer_groups: PeerGroups + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + bgp: Bgp | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + peer_groups: PeerGroups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyFlowSpecIpv4. + + + Subclass of AvdModel. + + Args: + bgp: Subclass of AvdModel. + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + peer_groups: Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class AddressFamilyFlowSpecIpv6(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"direction_in_action": {"type": str}, "direction_out_action": {"type": str}, "_custom_data": {"type": dict}} + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in_action: direction_in_action + direction_out_action: direction_out_action + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"missing_policy": {"type": MissingPolicy}, "_custom_data": {"type": dict}} + missing_policy: MissingPolicy + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, missing_policy: MissingPolicy | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + missing_policy: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ip_address": {"type": str}, "activate": {"type": bool}, "_custom_data": {"type": dict}} + ip_address: str + activate: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class PeerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "activate": {"type": bool}, "_custom_data": {"type": dict}} + name: str + """Peer-group name.""" + activate: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Peer-group name. + activate: activate + _custom_data: _custom_data + + """ + + class PeerGroups(AvdIndexedList[str, PeerGroupsItem]): + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PeerGroups._item_type = PeerGroupsItem + + _fields: ClassVar[dict] = { + "bgp": {"type": Bgp}, + "neighbors": {"type": Neighbors}, + "peer_groups": {"type": PeerGroups}, + "_custom_data": {"type": dict}, + } + bgp: Bgp + """Subclass of AvdModel.""" + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + peer_groups: PeerGroups + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + bgp: Bgp | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + peer_groups: PeerGroups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyFlowSpecIpv6. + + + Subclass of AvdModel. + + Args: + bgp: Subclass of AvdModel. + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + peer_groups: Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class AddressFamilyPathSelection(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "send": {"type": str}, "send_limit": {"type": int}, "_custom_data": {"type": dict}} + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"additional_paths": {"type": AdditionalPaths}, "_custom_data": {"type": dict}} + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, additional_paths: AdditionalPaths | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "send": {"type": str}, "send_limit": {"type": int}, "_custom_data": {"type": dict}} + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "activate": {"type": bool}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + ip_address: str + activate: bool | None + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class PeerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "send": {"type": str}, "send_limit": {"type": int}, "_custom_data": {"type": dict}} + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "activate": {"type": bool}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + name: str + """Peer-group name.""" + activate: bool | None + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Peer-group name. + activate: activate + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PeerGroups(AvdIndexedList[str, PeerGroupsItem]): + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PeerGroups._item_type = PeerGroupsItem + + _fields: ClassVar[dict] = { + "bgp": {"type": Bgp}, + "neighbors": {"type": Neighbors}, + "peer_groups": {"type": PeerGroups}, + "_custom_data": {"type": dict}, + } + bgp: Bgp + """Subclass of AvdModel.""" + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + peer_groups: PeerGroups + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + bgp: Bgp | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + peer_groups: PeerGroups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyPathSelection. + + + Subclass of AvdModel. + + Args: + bgp: Subclass of AvdModel. + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + peer_groups: Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class AddressFamilyVpnIpv4(AvdModel): + """Subclass of AvdModel.""" + + class PeerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class DefaultRoute(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "rcf": {"type": str}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultRoute. + + + Subclass of AvdModel. + + Args: + enabled: enabled + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + route_map: route_map + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "rcf_in": {"type": str}, + "rcf_out": {"type": str}, + "default_route": {"type": DefaultRoute}, + "_custom_data": {"type": dict}, + } + name: str + """Peer-group name.""" + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + rcf_in: str | None + """ + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + rcf_out: str | None + """ + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + default_route: DefaultRoute + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + rcf_in: str | None | UndefinedType = Undefined, + rcf_out: str | None | UndefinedType = Undefined, + default_route: DefaultRoute | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Peer-group name. + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + rcf_in: + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + rcf_out: + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + default_route: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PeerGroups(AvdIndexedList[str, PeerGroupsItem]): + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PeerGroups._item_type = PeerGroupsItem + + class Route(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"import_match_failure_action": {"type": str}, "_custom_data": {"type": dict}} + import_match_failure_action: Literal["discard"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + import_match_failure_action: Literal["discard"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Route. + + + Subclass of AvdModel. + + Args: + import_match_failure_action: import_match_failure_action + _custom_data: _custom_data + + """ + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + class DefaultRoute(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "rcf": {"type": str}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultRoute. + + + Subclass of AvdModel. + + Args: + enabled: enabled + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + route_map: route_map + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "rcf_in": {"type": str}, + "rcf_out": {"type": str}, + "default_route": {"type": DefaultRoute}, + "_custom_data": {"type": dict}, + } + ip_address: str + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + rcf_in: str | None + """ + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + rcf_out: str | None + """ + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + default_route: DefaultRoute + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + rcf_in: str | None | UndefinedType = Undefined, + rcf_out: str | None | UndefinedType = Undefined, + default_route: DefaultRoute | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + rcf_in: + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + rcf_out: + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + default_route: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class NeighborDefaultEncapsulationMplsNextHopSelf(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"source_interface": {"type": str}, "_custom_data": {"type": dict}} + source_interface: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, source_interface: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + NeighborDefaultEncapsulationMplsNextHopSelf. + + + Subclass of AvdModel. + + Args: + source_interface: source_interface + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "domain_identifier": {"type": str}, + "peer_groups": {"type": PeerGroups}, + "route": {"type": Route}, + "neighbors": {"type": Neighbors}, + "neighbor_default_encapsulation_mpls_next_hop_self": {"type": NeighborDefaultEncapsulationMplsNextHopSelf}, + "_custom_data": {"type": dict}, + } + domain_identifier: str | None + peer_groups: PeerGroups + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + route: Route + """Subclass of AvdModel.""" + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + neighbor_default_encapsulation_mpls_next_hop_self: NeighborDefaultEncapsulationMplsNextHopSelf + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + domain_identifier: str | None | UndefinedType = Undefined, + peer_groups: PeerGroups | UndefinedType = Undefined, + route: Route | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + neighbor_default_encapsulation_mpls_next_hop_self: NeighborDefaultEncapsulationMplsNextHopSelf | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyVpnIpv4. + + + Subclass of AvdModel. + + Args: + domain_identifier: domain_identifier + peer_groups: Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`). + route: Subclass of AvdModel. + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + neighbor_default_encapsulation_mpls_next_hop_self: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class AddressFamilyVpnIpv6(AvdModel): + """Subclass of AvdModel.""" + + class PeerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class DefaultRoute(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "rcf": {"type": str}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultRoute. + + + Subclass of AvdModel. + + Args: + enabled: enabled + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + route_map: route_map + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "rcf_in": {"type": str}, + "rcf_out": {"type": str}, + "default_route": {"type": DefaultRoute}, + "_custom_data": {"type": dict}, + } + name: str + """Peer-group name.""" + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + rcf_in: str | None + """ + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + rcf_out: str | None + """ + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + default_route: DefaultRoute + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + rcf_in: str | None | UndefinedType = Undefined, + rcf_out: str | None | UndefinedType = Undefined, + default_route: DefaultRoute | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Peer-group name. + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + rcf_in: + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + rcf_out: + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + default_route: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PeerGroups(AvdIndexedList[str, PeerGroupsItem]): + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PeerGroups._item_type = PeerGroupsItem + + class Route(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"import_match_failure_action": {"type": str}, "_custom_data": {"type": dict}} + import_match_failure_action: Literal["discard"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + import_match_failure_action: Literal["discard"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Route. + + + Subclass of AvdModel. + + Args: + import_match_failure_action: import_match_failure_action + _custom_data: _custom_data + + """ + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + class DefaultRoute(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "rcf": {"type": str}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultRoute. + + + Subclass of AvdModel. + + Args: + enabled: enabled + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + route_map: route_map + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "rcf_in": {"type": str}, + "rcf_out": {"type": str}, + "default_route": {"type": DefaultRoute}, + "_custom_data": {"type": dict}, + } + ip_address: str + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + rcf_in: str | None + """ + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + rcf_out: str | None + """ + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + default_route: DefaultRoute + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + rcf_in: str | None | UndefinedType = Undefined, + rcf_out: str | None | UndefinedType = Undefined, + default_route: DefaultRoute | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + rcf_in: + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + rcf_out: + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + default_route: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class NeighborDefaultEncapsulationMplsNextHopSelf(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"source_interface": {"type": str}, "_custom_data": {"type": dict}} + source_interface: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, source_interface: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + NeighborDefaultEncapsulationMplsNextHopSelf. + + + Subclass of AvdModel. + + Args: + source_interface: source_interface + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "domain_identifier": {"type": str}, + "peer_groups": {"type": PeerGroups}, + "route": {"type": Route}, + "neighbors": {"type": Neighbors}, + "neighbor_default_encapsulation_mpls_next_hop_self": {"type": NeighborDefaultEncapsulationMplsNextHopSelf}, + "_custom_data": {"type": dict}, + } + domain_identifier: str | None + peer_groups: PeerGroups + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + route: Route + """Subclass of AvdModel.""" + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + neighbor_default_encapsulation_mpls_next_hop_self: NeighborDefaultEncapsulationMplsNextHopSelf + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + domain_identifier: str | None | UndefinedType = Undefined, + peer_groups: PeerGroups | UndefinedType = Undefined, + route: Route | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + neighbor_default_encapsulation_mpls_next_hop_self: NeighborDefaultEncapsulationMplsNextHopSelf | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyVpnIpv6. + + + Subclass of AvdModel. + + Args: + domain_identifier: domain_identifier + peer_groups: Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`). + route: Subclass of AvdModel. + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + neighbor_default_encapsulation_mpls_next_hop_self: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "install": {"type": bool}, + "install_ecmp_primary": {"type": bool}, + "receive": {"type": bool}, + "send": {"type": str}, + "send_limit": {"type": int}, + "_custom_data": {"type": dict}, + } + install: bool | None + """Install BGP backup path.""" + install_ecmp_primary: bool | None + """Allow additional path with ECMP primary path.""" + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + install: bool | None | UndefinedType = Undefined, + install_ecmp_primary: bool | None | UndefinedType = Undefined, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + install: Install BGP backup path. + install_ecmp_primary: Allow additional path with ECMP primary path. + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "redistribute_internal": {"type": bool}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + redistribute_internal: bool | None + """Allow redistribution of iBGP routes into an Interior Gateway Protocol (IGP). EOS default is true.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + redistribute_internal: bool | None | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + redistribute_internal: Allow redistribution of iBGP routes into an Interior Gateway Protocol (IGP). EOS default is true. + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class EvpnMulticastAddressFamily(AvdModel): + """Subclass of AvdModel.""" + + class Ipv4(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"transit": {"type": bool}, "_custom_data": {"type": dict}} + transit: bool | None + """Enable EVPN multicast transit mode.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, transit: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Ipv4. + + + Subclass of AvdModel. + + Args: + transit: Enable EVPN multicast transit mode. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ipv4": {"type": Ipv4}, "_custom_data": {"type": dict}} + ipv4: Ipv4 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, ipv4: Ipv4 | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + EvpnMulticastAddressFamily. + + + Subclass of AvdModel. + + Args: + ipv4: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class EvpnMulticastGatewayDrElection(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"algorithm": {"type": str}, "preference_value": {"type": int}, "_custom_data": {"type": dict}} + algorithm: Literal["hrw", "modulus", "preference"] + """ + DR election algorithms: + hrw: Default selection based on highest random weight. + modulus: + Selection based on VLAN ID modulo number of candidates. + preference: Selection based on a + configured preference value. + """ + preference_value: int | None + """Required when `algorithm` is `preference`.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + algorithm: Literal["hrw", "modulus", "preference"] | UndefinedType = Undefined, + preference_value: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnMulticastGatewayDrElection. + + + Subclass of AvdModel. + + Args: + algorithm: + DR election algorithms: + hrw: Default selection based on highest random weight. + modulus: + Selection based on VLAN ID modulo number of candidates. + preference: Selection based on a + configured preference value. + preference_value: Required when `algorithm` is `preference`. + _custom_data: _custom_data + + """ + + class DefaultRouteExportsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "address_family": {"type": str}, + "always": {"type": bool}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "_custom_data": {"type": dict}, + } + address_family: Literal["evpn", "vpn-ipv4", "vpn-ipv6"] + always: bool | None + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + address_family: Literal["evpn", "vpn-ipv4", "vpn-ipv6"] | UndefinedType = Undefined, + always: bool | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultRouteExportsItem. + + + Subclass of AvdModel. + + Args: + address_family: address_family + always: always + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + _custom_data: _custom_data + + """ + + class DefaultRouteExports(AvdIndexedList[str, DefaultRouteExportsItem]): + """ + Subclass of AvdIndexedList with `DefaultRouteExportsItem` items. Primary key is `address_family` + (`str`). + """ + + _primary_key: ClassVar[str] = "address_family" + + DefaultRouteExports._item_type = DefaultRouteExportsItem + + class RouteTargets(AvdModel): + """Subclass of AvdModel.""" + + class ImportItem(AvdModel): + """Subclass of AvdModel.""" + + class RouteTargets(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + RouteTargets._item_type = str + + _fields: ClassVar[dict] = { + "address_family": {"type": str}, + "route_targets": {"type": RouteTargets}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "vpn_route_filter_rcf": {"type": str}, + "_custom_data": {"type": dict}, + } + address_family: str + route_targets: RouteTargets + """Subclass of AvdList with `str` items.""" + route_map: str | None + """Only applicable if `address_family` is one of `evpn`, `vpn-ipv4` or `vpn-ipv6`.""" + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + Only applicable if `address_family` + is one of `evpn`, `vpn-ipv4` or `vpn-ipv6`. + """ + vpn_route_filter_rcf: str | None + """ + RCF function name with parenthesis for filtering VPN routes. Also requires `rcf` to be set. + Example: + MyFunction(myarg). + Only applicable if `address_family` is one of `vpn-ipv4` or `vpn-ipv6`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + address_family: str | UndefinedType = Undefined, + route_targets: RouteTargets | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + vpn_route_filter_rcf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ImportItem. + + + Subclass of AvdModel. + + Args: + address_family: address_family + route_targets: Subclass of AvdList with `str` items. + route_map: Only applicable if `address_family` is one of `evpn`, `vpn-ipv4` or `vpn-ipv6`. + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + Only applicable if `address_family` + is one of `evpn`, `vpn-ipv4` or `vpn-ipv6`. + vpn_route_filter_rcf: + RCF function name with parenthesis for filtering VPN routes. Also requires `rcf` to be set. + Example: # fmt: skip + MyFunction(myarg). + Only applicable if `address_family` is one of `vpn-ipv4` or `vpn-ipv6`. + _custom_data: _custom_data + + """ + + class Import(AvdIndexedList[str, ImportItem]): + """Subclass of AvdIndexedList with `ImportItem` items. Primary key is `address_family` (`str`).""" + + _primary_key: ClassVar[str] = "address_family" + + Import._item_type = ImportItem + + class ExportItem(AvdModel): + """Subclass of AvdModel.""" + + class RouteTargets(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + RouteTargets._item_type = str + + _fields: ClassVar[dict] = { + "address_family": {"type": str}, + "route_targets": {"type": RouteTargets}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "vpn_route_filter_rcf": {"type": str}, + "_custom_data": {"type": dict}, + } + address_family: str + route_targets: RouteTargets + """Subclass of AvdList with `str` items.""" + route_map: str | None + """Only applicable if `address_family` is one of `evpn`, `vpn-ipv4` or `vpn-ipv6`.""" + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + Only applicable if `address_family` + is one of `evpn`, `vpn-ipv4` or `vpn-ipv6`. + """ + vpn_route_filter_rcf: str | None + """ + RCF function name with parenthesis for filtering VPN routes. Also requires `rcf` to be set. + Example: + MyFunction(myarg). + Only applicable if `address_family` is one of `vpn-ipv4` or `vpn-ipv6`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + address_family: str | UndefinedType = Undefined, + route_targets: RouteTargets | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + vpn_route_filter_rcf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ExportItem. + + + Subclass of AvdModel. + + Args: + address_family: address_family + route_targets: Subclass of AvdList with `str` items. + route_map: Only applicable if `address_family` is one of `evpn`, `vpn-ipv4` or `vpn-ipv6`. + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + Only applicable if `address_family` + is one of `evpn`, `vpn-ipv4` or `vpn-ipv6`. + vpn_route_filter_rcf: + RCF function name with parenthesis for filtering VPN routes. Also requires `rcf` to be set. + Example: # fmt: skip + MyFunction(myarg). + Only applicable if `address_family` is one of `vpn-ipv4` or `vpn-ipv6`. + _custom_data: _custom_data + + """ + + class Export(AvdIndexedList[str, ExportItem]): + """Subclass of AvdIndexedList with `ExportItem` items. Primary key is `address_family` (`str`).""" + + _primary_key: ClassVar[str] = "address_family" + + Export._item_type = ExportItem + + _fields: ClassVar[dict] = {"field_import": {"type": Import}, "export": {"type": Export}, "_custom_data": {"type": dict}} + _field_to_key_map: ClassVar[dict] = {"field_import": "import"} + _key_to_field_map: ClassVar[dict] = {"import": "field_import"} + field_import: Import + """Subclass of AvdIndexedList with `ImportItem` items. Primary key is `address_family` (`str`).""" + export: Export + """Subclass of AvdIndexedList with `ExportItem` items. Primary key is `address_family` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + field_import: Import | UndefinedType = Undefined, + export: Export | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouteTargets. + + + Subclass of AvdModel. + + Args: + field_import: Subclass of AvdIndexedList with `ImportItem` items. Primary key is `address_family` (`str`). + export: Subclass of AvdIndexedList with `ExportItem` items. Primary key is `address_family` (`str`). + _custom_data: _custom_data + + """ + + class NetworksItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + prefix: str + """IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I".""" + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix: str | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NetworksItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I". + route_map: route_map + _custom_data: _custom_data + + """ + + class Networks(AvdIndexedList[str, NetworksItem]): + """Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`).""" + + _primary_key: ClassVar[str] = "prefix" + + Networks._item_type = NetworksItem + + class MaximumPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"paths": {"type": int}, "ecmp": {"type": int}, "_custom_data": {"type": dict}} + paths: int + ecmp: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + paths: int | UndefinedType = Undefined, + ecmp: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MaximumPaths. + + + Subclass of AvdModel. + + Args: + paths: paths + ecmp: ecmp + _custom_data: _custom_data + + """ + + class Updates(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"wait_for_convergence": {"type": bool}, "wait_install": {"type": bool}, "_custom_data": {"type": dict}} + wait_for_convergence: bool | None + """ + Disables FIB updates and route advertisement when the BGP instance is initiated until the BGP + convergence state is reached. + """ + wait_install: bool | None + """ + Do not advertise reachability to a prefix until that prefix has been installed in hardware. + This + will eliminate any temporary black holes due to a BGP speaker advertising reachability to a prefix + that may not yet be installed into the forwarding plane. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + wait_for_convergence: bool | None | UndefinedType = Undefined, + wait_install: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Updates. + + + Subclass of AvdModel. + + Args: + wait_for_convergence: + Disables FIB updates and route advertisement when the BGP instance is initiated until the BGP + convergence state is reached. + wait_install: + Do not advertise reachability to a prefix until that prefix has been installed in hardware. + This + will eliminate any temporary black holes due to a BGP speaker advertising reachability to a prefix + that may not yet be installed into the forwarding plane. + _custom_data: _custom_data + + """ + + class ListenRangesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "prefix": {"type": str}, + "peer_id_include_router_id": {"type": bool}, + "peer_group": {"type": str}, + "peer_filter": {"type": str}, + "remote_as": {"type": str}, + "_custom_data": {"type": dict}, + } + prefix: str | None + """IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I".""" + peer_id_include_router_id: bool | None + """Include router ID as part of peer filter.""" + peer_group: str | None + """Peer-group name.""" + peer_filter: str | None + """ + Peer-filter name. + note: `peer_filter`` or `remote_as` is required but mutually exclusive. + If both + are defined, peer_filter takes precedence. + """ + remote_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix: str | None | UndefinedType = Undefined, + peer_id_include_router_id: bool | None | UndefinedType = Undefined, + peer_group: str | None | UndefinedType = Undefined, + peer_filter: str | None | UndefinedType = Undefined, + remote_as: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ListenRangesItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I". + peer_id_include_router_id: Include router ID as part of peer filter. + peer_group: Peer-group name. + peer_filter: + Peer-filter name. + note: `peer_filter`` or `remote_as` is required but mutually exclusive. + If both + are defined, peer_filter takes precedence. + remote_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + _custom_data: _custom_data + + """ + + class ListenRanges(AvdList[ListenRangesItem]): + """Subclass of AvdList with `ListenRangesItem` items.""" + + ListenRanges._item_type = ListenRangesItem + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + class RemovePrivateAs(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "all": {"type": bool}, "replace_as": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + all: bool | None + replace_as: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + all: bool | None | UndefinedType = Undefined, + replace_as: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemovePrivateAs. + + + Subclass of AvdModel. + + Args: + enabled: enabled + all: all + replace_as: replace_as + _custom_data: _custom_data + + """ + + class RemovePrivateAsIngress(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "replace_as": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + replace_as: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + replace_as: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemovePrivateAsIngress. + + + Subclass of AvdModel. + + Args: + enabled: enabled + replace_as: replace_as + _custom_data: _custom_data + + """ + + class AsPath(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"remote_as_replace_out": {"type": bool}, "prepend_own_disabled": {"type": bool}, "_custom_data": {"type": dict}} + remote_as_replace_out: bool | None + """Replace AS number with local AS number.""" + prepend_own_disabled: bool | None + """Disable prepending own AS number to AS path.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + remote_as_replace_out: bool | None | UndefinedType = Undefined, + prepend_own_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AsPath. + + + Subclass of AvdModel. + + Args: + remote_as_replace_out: Replace AS number with local AS number. + prepend_own_disabled: Disable prepending own AS number to AS path. + _custom_data: _custom_data + + """ + + class BfdTimers(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interval": {"type": int}, "min_rx": {"type": int}, "multiplier": {"type": int}, "_custom_data": {"type": dict}} + interval: int + """Interval in milliseconds.""" + min_rx: int + """Rate in milliseconds.""" + multiplier: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | UndefinedType = Undefined, + min_rx: int | UndefinedType = Undefined, + multiplier: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BfdTimers. + + + Subclass of AvdModel. + + Args: + interval: Interval in milliseconds. + min_rx: Rate in milliseconds. + multiplier: multiplier + _custom_data: _custom_data + + """ + + class RibInPrePolicyRetain(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "all": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + all: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + all: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RibInPrePolicyRetain. + + + Subclass of AvdModel. + + Args: + enabled: enabled + all: all + _custom_data: _custom_data + + """ + + class AllowasIn(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "times": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool | None + times: int | None + """Number of local ASNs allowed in a BGP update.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + times: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AllowasIn. + + + Subclass of AvdModel. + + Args: + enabled: enabled + times: Number of local ASNs allowed in a BGP update. + _custom_data: _custom_data + + """ + + class DefaultOriginate(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "always": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + always: bool | None + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + always: bool | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultOriginate. + + + Subclass of AvdModel. + + Args: + enabled: enabled + always: always + route_map: route_map + _custom_data: _custom_data + + """ + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "send": {"type": str}, "send_limit": {"type": int}, "_custom_data": {"type": dict}} + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "peer_group": {"type": str}, + "remote_as": {"type": str}, + "password": {"type": str}, + "passive": {"type": bool}, + "remove_private_as": {"type": RemovePrivateAs}, + "remove_private_as_ingress": {"type": RemovePrivateAsIngress}, + "weight": {"type": int}, + "local_as": {"type": str}, + "as_path": {"type": AsPath}, + "description": {"type": str}, + "route_reflector_client": {"type": bool}, + "ebgp_multihop": {"type": int}, + "next_hop_self": {"type": bool}, + "shutdown": {"type": bool}, + "bfd": {"type": bool}, + "bfd_timers": {"type": BfdTimers}, + "timers": {"type": str}, + "rib_in_pre_policy_retain": {"type": RibInPrePolicyRetain}, + "send_community": {"type": str}, + "maximum_routes": {"type": int}, + "maximum_routes_warning_limit": {"type": str}, + "maximum_routes_warning_only": {"type": bool}, + "allowas_in": {"type": AllowasIn}, + "default_originate": {"type": DefaultOriginate}, + "update_source": {"type": str}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + ip_address: str + peer_group: str | None + """Peer-group name.""" + remote_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + password: str | None + passive: bool | None + remove_private_as: RemovePrivateAs + """ + Remove private AS numbers in outbound AS path. + + Subclass of AvdModel. + """ + remove_private_as_ingress: RemovePrivateAsIngress + """Subclass of AvdModel.""" + weight: int | None + local_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + as_path: AsPath + """ + BGP AS-PATH options. + + Subclass of AvdModel. + """ + description: str | None + route_reflector_client: bool | None + ebgp_multihop: int | None + """Time-to-live in range of hops.""" + next_hop_self: bool | None + shutdown: bool | None + bfd: bool | None + """Enable BFD.""" + bfd_timers: BfdTimers + """ + Override default BFD timers. BFD must be enabled with `bfd: true`. + + Subclass of AvdModel. + """ + timers: str | None + """BGP Keepalive and Hold Timer values in seconds as string "<0-3600> <0-3600>".""" + rib_in_pre_policy_retain: RibInPrePolicyRetain + """Subclass of AvdModel.""" + send_community: str | None + """'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'.""" + maximum_routes: int | None + maximum_routes_warning_limit: str | None + """ + Maximum number of routes after which a warning is issued (0 means never warn) or + Percentage of + maximum number of routes at which to warn ("<1-100> percent"). + """ + maximum_routes_warning_only: bool | None + allowas_in: AllowasIn + """Subclass of AvdModel.""" + default_originate: DefaultOriginate + """Subclass of AvdModel.""" + update_source: str | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + peer_group: str | None | UndefinedType = Undefined, + remote_as: str | None | UndefinedType = Undefined, + password: str | None | UndefinedType = Undefined, + passive: bool | None | UndefinedType = Undefined, + remove_private_as: RemovePrivateAs | UndefinedType = Undefined, + remove_private_as_ingress: RemovePrivateAsIngress | UndefinedType = Undefined, + weight: int | None | UndefinedType = Undefined, + local_as: str | None | UndefinedType = Undefined, + as_path: AsPath | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + route_reflector_client: bool | None | UndefinedType = Undefined, + ebgp_multihop: int | None | UndefinedType = Undefined, + next_hop_self: bool | None | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + bfd: bool | None | UndefinedType = Undefined, + bfd_timers: BfdTimers | UndefinedType = Undefined, + timers: str | None | UndefinedType = Undefined, + rib_in_pre_policy_retain: RibInPrePolicyRetain | UndefinedType = Undefined, + send_community: str | None | UndefinedType = Undefined, + maximum_routes: int | None | UndefinedType = Undefined, + maximum_routes_warning_limit: str | None | UndefinedType = Undefined, + maximum_routes_warning_only: bool | None | UndefinedType = Undefined, + allowas_in: AllowasIn | UndefinedType = Undefined, + default_originate: DefaultOriginate | UndefinedType = Undefined, + update_source: str | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + peer_group: Peer-group name. + remote_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + password: password + passive: passive + remove_private_as: + Remove private AS numbers in outbound AS path. + + Subclass of AvdModel. + remove_private_as_ingress: Subclass of AvdModel. + weight: weight + local_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + as_path: + BGP AS-PATH options. + + Subclass of AvdModel. + description: description + route_reflector_client: route_reflector_client + ebgp_multihop: Time-to-live in range of hops. + next_hop_self: next_hop_self + shutdown: shutdown + bfd: Enable BFD. + bfd_timers: + Override default BFD timers. BFD must be enabled with `bfd: true`. + + Subclass of AvdModel. + timers: BGP Keepalive and Hold Timer values in seconds as string "<0-3600> <0-3600>". + rib_in_pre_policy_retain: Subclass of AvdModel. + send_community: 'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'. + maximum_routes: maximum_routes + maximum_routes_warning_limit: + Maximum number of routes after which a warning is issued (0 means never warn) or + Percentage of + maximum number of routes at which to warn ("<1-100> percent"). + maximum_routes_warning_only: maximum_routes_warning_only + allowas_in: Subclass of AvdModel. + default_originate: Subclass of AvdModel. + update_source: update_source + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class NeighborInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "remote_as": {"type": str}, + "peer_group": {"type": str}, + "peer_filter": {"type": str}, + "description": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Interface name.""" + remote_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + peer_group: str | None + """Peer-group name.""" + peer_filter: str | None + """Peer-filter name.""" + description: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + remote_as: str | None | UndefinedType = Undefined, + peer_group: str | None | UndefinedType = Undefined, + peer_filter: str | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: Interface name. + remote_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + peer_group: Peer-group name. + peer_filter: Peer-filter name. + description: description + _custom_data: _custom_data + + """ + + class NeighborInterfaces(AvdIndexedList[str, NeighborInterfacesItem]): + """Subclass of AvdIndexedList with `NeighborInterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + NeighborInterfaces._item_type = NeighborInterfacesItem + + class Redistribute(AvdModel): + """Subclass of AvdModel.""" + + class AttachedHost(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AttachedHost. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Connected(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Connected. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Dynamic(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "rcf": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dynamic. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + _custom_data: _custom_data + + """ + + class Isis(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "isis_level": {"type": str}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + isis_level: Literal["level-1", "level-2", "level-1-2"] | None + """Redistribute IS-IS route level.""" + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + isis_level: Literal["level-1", "level-2", "level-1-2"] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Isis. + + + Subclass of AvdModel. + + Args: + enabled: enabled + isis_level: Redistribute IS-IS route level. + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Ospf(AvdModel): + """Subclass of AvdModel.""" + + class MatchExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchInternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchInternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchNssaExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "nssa_type": {"type": int}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + nssa_type: Literal[1, 2] | None + """NSSA External Type Number.""" + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + nssa_type: Literal[1, 2] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchNssaExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + nssa_type: NSSA External Type Number. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "match_external": {"type": MatchExternal}, + "match_internal": {"type": MatchInternal}, + "match_nssa_external": {"type": MatchNssaExternal}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Redistribute OSPF routes.""" + match_external: MatchExternal + """ + Redistribute OSPF routes learned from external sources. + + Subclass of AvdModel. + """ + match_internal: MatchInternal + """ + Redistribute OSPF routes learned from internal sources. + + Subclass of AvdModel. + """ + match_nssa_external: MatchNssaExternal + """ + Redistribute OSPF routes learned from external NSSA sources. + + Subclass of AvdModel. + """ + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + match_external: MatchExternal | UndefinedType = Undefined, + match_internal: MatchInternal | UndefinedType = Undefined, + match_nssa_external: MatchNssaExternal | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospf. + + + Subclass of AvdModel. + + Args: + enabled: Redistribute OSPF routes. + match_external: + Redistribute OSPF routes learned from external sources. + + Subclass of AvdModel. + match_internal: + Redistribute OSPF routes learned from internal sources. + + Subclass of AvdModel. + match_nssa_external: + Redistribute OSPF routes learned from external NSSA sources. + + Subclass of AvdModel. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Ospfv3(AvdModel): + """Subclass of AvdModel.""" + + class MatchExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchInternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchInternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchNssaExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "nssa_type": {"type": int}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + nssa_type: Literal[1, 2] | None + """NSSA External Type Number.""" + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + nssa_type: Literal[1, 2] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchNssaExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + nssa_type: NSSA External Type Number. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "match_external": {"type": MatchExternal}, + "match_internal": {"type": MatchInternal}, + "match_nssa_external": {"type": MatchNssaExternal}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Redistribute OSPFv3 routes.""" + match_external: MatchExternal + """ + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + """ + match_internal: MatchInternal + """ + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + """ + match_nssa_external: MatchNssaExternal + """ + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + """ + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + match_external: MatchExternal | UndefinedType = Undefined, + match_internal: MatchInternal | UndefinedType = Undefined, + match_nssa_external: MatchNssaExternal | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospfv3. + + + Subclass of AvdModel. + + Args: + enabled: Redistribute OSPFv3 routes. + match_external: + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + match_internal: + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + match_nssa_external: + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Rip(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Rip. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Static(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Static. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class User(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "rcf": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + User. + + + Subclass of AvdModel. + + Args: + enabled: enabled + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "attached_host": {"type": AttachedHost}, + "bgp": {"type": Bgp}, + "connected": {"type": Connected}, + "dynamic": {"type": Dynamic}, + "isis": {"type": Isis}, + "ospf": {"type": Ospf}, + "ospfv3": {"type": Ospfv3}, + "rip": {"type": Rip}, + "static": {"type": Static}, + "user": {"type": User}, + "_custom_data": {"type": dict}, + } + attached_host: AttachedHost + """Subclass of AvdModel.""" + bgp: Bgp + """Subclass of AvdModel.""" + connected: Connected + """Subclass of AvdModel.""" + dynamic: Dynamic + """Subclass of AvdModel.""" + isis: Isis + """Subclass of AvdModel.""" + ospf: Ospf + """Subclass of AvdModel.""" + ospfv3: Ospfv3 + """Subclass of AvdModel.""" + rip: Rip + """Subclass of AvdModel.""" + static: Static + """Subclass of AvdModel.""" + user: User + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + attached_host: AttachedHost | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + connected: Connected | UndefinedType = Undefined, + dynamic: Dynamic | UndefinedType = Undefined, + isis: Isis | UndefinedType = Undefined, + ospf: Ospf | UndefinedType = Undefined, + ospfv3: Ospfv3 | UndefinedType = Undefined, + rip: Rip | UndefinedType = Undefined, + static: Static | UndefinedType = Undefined, + user: User | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Redistribute. + + + Subclass of AvdModel. + + Args: + attached_host: Subclass of AvdModel. + bgp: Subclass of AvdModel. + connected: Subclass of AvdModel. + dynamic: Subclass of AvdModel. + isis: Subclass of AvdModel. + ospf: Subclass of AvdModel. + ospfv3: Subclass of AvdModel. + rip: Subclass of AvdModel. + static: Subclass of AvdModel. + user: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class RedistributeRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "source_protocol": {"type": str}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "rcf": {"type": str}, + "ospf_route_type": {"type": str}, + "_custom_data": {"type": dict}, + } + source_protocol: str + route_map: str | None + include_leaked: bool | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only applicable if `source_protocol` is one of `connected`, + `dynamic`, `isis`, `static` and `user`. + """ + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None + """ + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospf' and + 'ospfv3'. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source_protocol: str | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] + | None + | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RedistributeRoutesItem. + + + Subclass of AvdModel. + + Args: + source_protocol: source_protocol + route_map: route_map + include_leaked: include_leaked + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only applicable if `source_protocol` is one of `connected`, + `dynamic`, `isis`, `static` and `user`. + ospf_route_type: + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospf' and + 'ospfv3'. + _custom_data: _custom_data + + """ + + class RedistributeRoutes(AvdList[RedistributeRoutesItem]): + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + + RedistributeRoutes._item_type = RedistributeRoutesItem + + class AggregateAddressesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "prefix": {"type": str}, + "advertise_only": {"type": bool}, + "as_set": {"type": bool}, + "summary_only": {"type": bool}, + "attribute_map": {"type": str}, + "match_map": {"type": str}, + "_custom_data": {"type": dict}, + } + prefix: str + """IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I".""" + advertise_only: bool | None + as_set: bool | None + summary_only: bool | None + attribute_map: str | None + match_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix: str | UndefinedType = Undefined, + advertise_only: bool | None | UndefinedType = Undefined, + as_set: bool | None | UndefinedType = Undefined, + summary_only: bool | None | UndefinedType = Undefined, + attribute_map: str | None | UndefinedType = Undefined, + match_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AggregateAddressesItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I". + advertise_only: advertise_only + as_set: as_set + summary_only: summary_only + attribute_map: attribute_map + match_map: match_map + _custom_data: _custom_data + + """ + + class AggregateAddresses(AvdIndexedList[str, AggregateAddressesItem]): + """Subclass of AvdIndexedList with `AggregateAddressesItem` items. Primary key is `prefix` (`str`).""" + + _primary_key: ClassVar[str] = "prefix" + + AggregateAddresses._item_type = AggregateAddressesItem + + class AddressFamilyIpv4(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"direction_in_action": {"type": str}, "direction_out_action": {"type": str}, "_custom_data": {"type": dict}} + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in_action: direction_in_action + direction_out_action: direction_out_action + _custom_data: _custom_data + + """ + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "install": {"type": bool}, + "install_ecmp_primary": {"type": bool}, + "receive": {"type": bool}, + "send": {"type": str}, + "send_limit": {"type": int}, + "_custom_data": {"type": dict}, + } + install: bool | None + """Install BGP backup path.""" + install_ecmp_primary: bool | None + """Allow additional path with ECMP primary path.""" + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + install: bool | None | UndefinedType = Undefined, + install_ecmp_primary: bool | None | UndefinedType = Undefined, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + install: Install BGP backup path. + install_ecmp_primary: Allow additional path with ECMP primary path. + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "missing_policy": {"type": MissingPolicy}, + "additional_paths": {"type": AdditionalPaths}, + "redistribute_internal": {"type": bool}, + "_custom_data": {"type": dict}, + } + missing_policy: MissingPolicy + """Subclass of AvdModel.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + redistribute_internal: bool | None + """Allow redistribution of iBGP routes into an Interior Gateway Protocol (IGP). EOS default is true.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + missing_policy: MissingPolicy | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + redistribute_internal: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + missing_policy: Subclass of AvdModel. + additional_paths: Subclass of AvdModel. + redistribute_internal: Allow redistribution of iBGP routes into an Interior Gateway Protocol (IGP). EOS default is true. + _custom_data: _custom_data + + """ + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + class NextHop(AvdModel): + """Subclass of AvdModel.""" + + class AddressFamilyIpv6(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "originate": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool + originate: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + originate: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv6. + + + Subclass of AvdModel. + + Args: + enabled: enabled + originate: originate + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"address_family_ipv6": {"type": AddressFamilyIpv6}, "_custom_data": {"type": dict}} + address_family_ipv6: AddressFamilyIpv6 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + address_family_ipv6: AddressFamilyIpv6 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NextHop. + + + Subclass of AvdModel. + + Args: + address_family_ipv6: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "receive": {"type": bool}, + "send": {"type": str}, + "send_limit": {"type": int}, + "_custom_data": {"type": dict}, + } + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "rcf_in": {"type": str}, + "rcf_out": {"type": str}, + "prefix_list_in": {"type": str}, + "prefix_list_out": {"type": str}, + "next_hop": {"type": NextHop}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + ip_address: str + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + rcf_in: str | None + """ + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + rcf_out: str | None + """ + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + prefix_list_in: str | None + """Inbound prefix-list name.""" + prefix_list_out: str | None + """Outbound prefix-list name.""" + next_hop: NextHop + """Subclass of AvdModel.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + rcf_in: str | None | UndefinedType = Undefined, + rcf_out: str | None | UndefinedType = Undefined, + prefix_list_in: str | None | UndefinedType = Undefined, + prefix_list_out: str | None | UndefinedType = Undefined, + next_hop: NextHop | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + rcf_in: + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + rcf_out: + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + prefix_list_in: Inbound prefix-list name. + prefix_list_out: Outbound prefix-list name. + next_hop: Subclass of AvdModel. + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class NetworksItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + prefix: str + """IPv4 prefix "A.B.C.D/E".""" + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix: str | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NetworksItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv4 prefix "A.B.C.D/E". + route_map: route_map + _custom_data: _custom_data + + """ + + class Networks(AvdIndexedList[str, NetworksItem]): + """Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`).""" + + _primary_key: ClassVar[str] = "prefix" + + Networks._item_type = NetworksItem + + class Redistribute(AvdModel): + """Subclass of AvdModel.""" + + class AttachedHost(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AttachedHost. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Connected(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Connected. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Dynamic(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "rcf": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dynamic. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + _custom_data: _custom_data + + """ + + class Isis(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "isis_level": {"type": str}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + isis_level: Literal["level-1", "level-2", "level-1-2"] | None + """Redistribute IS-IS route level.""" + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + isis_level: Literal["level-1", "level-2", "level-1-2"] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Isis. + + + Subclass of AvdModel. + + Args: + enabled: enabled + isis_level: Redistribute IS-IS route level. + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Ospf(AvdModel): + """Subclass of AvdModel.""" + + class MatchExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchInternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchInternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchNssaExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "nssa_type": {"type": int}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + nssa_type: Literal[1, 2] | None + """NSSA External Type Number.""" + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + nssa_type: Literal[1, 2] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchNssaExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + nssa_type: NSSA External Type Number. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "match_external": {"type": MatchExternal}, + "match_internal": {"type": MatchInternal}, + "match_nssa_external": {"type": MatchNssaExternal}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Redistribute OSPF routes.""" + match_external: MatchExternal + """ + Redistribute OSPF routes learned from external sources. + + Subclass of AvdModel. + """ + match_internal: MatchInternal + """ + Redistribute OSPF routes learned from internal sources. + + Subclass of AvdModel. + """ + match_nssa_external: MatchNssaExternal + """ + Redistribute OSPF routes learned from external NSSA sources. + + Subclass of AvdModel. + """ + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + match_external: MatchExternal | UndefinedType = Undefined, + match_internal: MatchInternal | UndefinedType = Undefined, + match_nssa_external: MatchNssaExternal | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospf. + + + Subclass of AvdModel. + + Args: + enabled: Redistribute OSPF routes. + match_external: + Redistribute OSPF routes learned from external sources. + + Subclass of AvdModel. + match_internal: + Redistribute OSPF routes learned from internal sources. + + Subclass of AvdModel. + match_nssa_external: + Redistribute OSPF routes learned from external NSSA sources. + + Subclass of AvdModel. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Ospfv3(AvdModel): + """Subclass of AvdModel.""" + + class MatchExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchInternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchInternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchNssaExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "nssa_type": {"type": int}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + nssa_type: Literal[1, 2] | None + """NSSA External Type Number.""" + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + nssa_type: Literal[1, 2] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchNssaExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + nssa_type: NSSA External Type Number. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "match_external": {"type": MatchExternal}, + "match_internal": {"type": MatchInternal}, + "match_nssa_external": {"type": MatchNssaExternal}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Redistribute OSPFv3 routes.""" + match_external: MatchExternal + """ + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + """ + match_internal: MatchInternal + """ + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + """ + match_nssa_external: MatchNssaExternal + """ + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + """ + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + match_external: MatchExternal | UndefinedType = Undefined, + match_internal: MatchInternal | UndefinedType = Undefined, + match_nssa_external: MatchNssaExternal | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospfv3. + + + Subclass of AvdModel. + + Args: + enabled: Redistribute OSPFv3 routes. + match_external: + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + match_internal: + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + match_nssa_external: + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Rip(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Rip. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Static(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Static. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class User(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "rcf": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + User. + + + Subclass of AvdModel. + + Args: + enabled: enabled + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "attached_host": {"type": AttachedHost}, + "bgp": {"type": Bgp}, + "connected": {"type": Connected}, + "dynamic": {"type": Dynamic}, + "isis": {"type": Isis}, + "ospf": {"type": Ospf}, + "ospfv3": {"type": Ospfv3}, + "rip": {"type": Rip}, + "static": {"type": Static}, + "user": {"type": User}, + "_custom_data": {"type": dict}, + } + attached_host: AttachedHost + """Subclass of AvdModel.""" + bgp: Bgp + """Subclass of AvdModel.""" + connected: Connected + """Subclass of AvdModel.""" + dynamic: Dynamic + """Subclass of AvdModel.""" + isis: Isis + """Subclass of AvdModel.""" + ospf: Ospf + """Subclass of AvdModel.""" + ospfv3: Ospfv3 + """Subclass of AvdModel.""" + rip: Rip + """Subclass of AvdModel.""" + static: Static + """Subclass of AvdModel.""" + user: User + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + attached_host: AttachedHost | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + connected: Connected | UndefinedType = Undefined, + dynamic: Dynamic | UndefinedType = Undefined, + isis: Isis | UndefinedType = Undefined, + ospf: Ospf | UndefinedType = Undefined, + ospfv3: Ospfv3 | UndefinedType = Undefined, + rip: Rip | UndefinedType = Undefined, + static: Static | UndefinedType = Undefined, + user: User | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Redistribute. + + + Subclass of AvdModel. + + Args: + attached_host: Subclass of AvdModel. + bgp: Subclass of AvdModel. + connected: Subclass of AvdModel. + dynamic: Subclass of AvdModel. + isis: Subclass of AvdModel. + ospf: Subclass of AvdModel. + ospfv3: Subclass of AvdModel. + rip: Subclass of AvdModel. + static: Subclass of AvdModel. + user: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class RedistributeRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "source_protocol": {"type": str}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "rcf": {"type": str}, + "ospf_route_type": {"type": str}, + "_custom_data": {"type": dict}, + } + source_protocol: Literal["attached-host", "bgp", "connected", "dynamic", "isis", "ospf", "ospfv3", "rip", "static", "user"] + route_map: str | None + include_leaked: bool | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only applicable if `source_protocol` is one of `connected`, + `dynamic`, `isis`, `static` and `user`. + """ + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None + """ + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospf' and + 'ospfv3'. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source_protocol: Literal["attached-host", "bgp", "connected", "dynamic", "isis", "ospf", "ospfv3", "rip", "static", "user"] + | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] + | None + | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RedistributeRoutesItem. + + + Subclass of AvdModel. + + Args: + source_protocol: source_protocol + route_map: route_map + include_leaked: include_leaked + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only applicable if `source_protocol` is one of `connected`, + `dynamic`, `isis`, `static` and `user`. + ospf_route_type: + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospf' and + 'ospfv3'. + _custom_data: _custom_data + + """ + + class RedistributeRoutes(AvdList[RedistributeRoutesItem]): + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + + RedistributeRoutes._item_type = RedistributeRoutesItem + + _fields: ClassVar[dict] = { + "bgp": {"type": Bgp}, + "neighbors": {"type": Neighbors}, + "networks": {"type": Networks}, + "redistribute": {"type": Redistribute}, + "redistribute_routes": {"type": RedistributeRoutes}, + "_custom_data": {"type": dict}, + } + bgp: Bgp + """Subclass of AvdModel.""" + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + networks: Networks + """Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`).""" + redistribute: Redistribute + """ + Redistribute routes in to BGP. + + Subclass of AvdModel. + """ + redistribute_routes: RedistributeRoutes + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + bgp: Bgp | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + networks: Networks | UndefinedType = Undefined, + redistribute: Redistribute | UndefinedType = Undefined, + redistribute_routes: RedistributeRoutes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv4. + + + Subclass of AvdModel. + + Args: + bgp: Subclass of AvdModel. + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + networks: Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`). + redistribute: + Redistribute routes in to BGP. + + Subclass of AvdModel. + redistribute_routes: Subclass of AvdList with `RedistributeRoutesItem` items. + _custom_data: _custom_data + + """ + + class AddressFamilyIpv6(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"direction_in_action": {"type": str}, "direction_out_action": {"type": str}, "_custom_data": {"type": dict}} + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in_action: direction_in_action + direction_out_action: direction_out_action + _custom_data: _custom_data + + """ + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "install": {"type": bool}, + "install_ecmp_primary": {"type": bool}, + "receive": {"type": bool}, + "send": {"type": str}, + "send_limit": {"type": int}, + "_custom_data": {"type": dict}, + } + install: bool | None + """Install BGP backup path.""" + install_ecmp_primary: bool | None + """Allow additional path with ECMP primary path.""" + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + install: bool | None | UndefinedType = Undefined, + install_ecmp_primary: bool | None | UndefinedType = Undefined, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + install: Install BGP backup path. + install_ecmp_primary: Allow additional path with ECMP primary path. + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "missing_policy": {"type": MissingPolicy}, + "additional_paths": {"type": AdditionalPaths}, + "redistribute_internal": {"type": bool}, + "_custom_data": {"type": dict}, + } + missing_policy: MissingPolicy + """Subclass of AvdModel.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + redistribute_internal: bool | None + """Allow redistribution of iBGP routes into an Interior Gateway Protocol (IGP). EOS default is true.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + missing_policy: MissingPolicy | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + redistribute_internal: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + missing_policy: Subclass of AvdModel. + additional_paths: Subclass of AvdModel. + redistribute_internal: Allow redistribution of iBGP routes into an Interior Gateway Protocol (IGP). EOS default is true. + _custom_data: _custom_data + + """ + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "receive": {"type": bool}, + "send": {"type": str}, + "send_limit": {"type": int}, + "_custom_data": {"type": dict}, + } + receive: bool | None + """Enable or disable reception of additional-paths.""" + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None + """ + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + """ + send_limit: int | None + """ + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + receive: bool | None | UndefinedType = Undefined, + send: Literal["any", "backup", "ecmp", "limit", "disabled"] | None | UndefinedType = Undefined, + send_limit: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: Enable or disable reception of additional-paths. + send: + Select an option to send multiple paths for same prefix through bgp updates. + any: Send any eligible + path. + backup: Best path and installed backup path. + ecmp: All paths in best path ECMP group. + limit: + Limit to n eligible paths. + disabled: Disable sending any paths. + send_limit: + Number of paths to send through bgp updates. For this setting, `send` must be set to `limit` or + `ecmp`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "rcf_in": {"type": str}, + "rcf_out": {"type": str}, + "prefix_list_in": {"type": str}, + "prefix_list_out": {"type": str}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + ip_address: str + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + rcf_in: str | None + """ + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + rcf_out: str | None + """ + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + """ + prefix_list_in: str | None + """Inbound prefix-list name.""" + prefix_list_out: str | None + """Outbound prefix-list name.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + rcf_in: str | None | UndefinedType = Undefined, + rcf_out: str | None | UndefinedType = Undefined, + prefix_list_in: str | None | UndefinedType = Undefined, + prefix_list_out: str | None | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + rcf_in: + Inbound RCF function name with parenthesis. + Example: MyFunction(myarg). + rcf_out: + Outbound RCF function name with parenthesis. + Example: MyFunction(myarg). + prefix_list_in: Inbound prefix-list name. + prefix_list_out: Outbound prefix-list name. + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class NetworksItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + prefix: str + """IPv6 prefix "A:B:C:D:E:F:G:H/I".""" + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix: str | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NetworksItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv6 prefix "A:B:C:D:E:F:G:H/I". + route_map: route_map + _custom_data: _custom_data + + """ + + class Networks(AvdIndexedList[str, NetworksItem]): + """Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`).""" + + _primary_key: ClassVar[str] = "prefix" + + Networks._item_type = NetworksItem + + class Redistribute(AvdModel): + """Subclass of AvdModel.""" + + class AttachedHost(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AttachedHost. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Connected(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Connected. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Dhcp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dhcp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Dynamic(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "rcf": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dynamic. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + _custom_data: _custom_data + + """ + + class Isis(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "isis_level": {"type": str}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + isis_level: Literal["level-1", "level-2", "level-1-2"] | None + """Redistribute IS-IS route level.""" + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + isis_level: Literal["level-1", "level-2", "level-1-2"] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Isis. + + + Subclass of AvdModel. + + Args: + enabled: enabled + isis_level: Redistribute IS-IS route level. + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Ospfv3(AvdModel): + """Subclass of AvdModel.""" + + class MatchExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchInternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchInternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchNssaExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "nssa_type": {"type": int}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + nssa_type: Literal[1, 2] | None + """NSSA External Type Number.""" + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + nssa_type: Literal[1, 2] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchNssaExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + nssa_type: NSSA External Type Number. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "match_external": {"type": MatchExternal}, + "match_internal": {"type": MatchInternal}, + "match_nssa_external": {"type": MatchNssaExternal}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Redistribute OSPFv3 routes.""" + match_external: MatchExternal + """ + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + """ + match_internal: MatchInternal + """ + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + """ + match_nssa_external: MatchNssaExternal + """ + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + """ + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + match_external: MatchExternal | UndefinedType = Undefined, + match_internal: MatchInternal | UndefinedType = Undefined, + match_nssa_external: MatchNssaExternal | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospfv3. + + + Subclass of AvdModel. + + Args: + enabled: Redistribute OSPFv3 routes. + match_external: + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + match_internal: + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + match_nssa_external: + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Static(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Static. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class User(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "rcf": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + User. + + + Subclass of AvdModel. + + Args: + enabled: enabled + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "attached_host": {"type": AttachedHost}, + "bgp": {"type": Bgp}, + "connected": {"type": Connected}, + "dhcp": {"type": Dhcp}, + "dynamic": {"type": Dynamic}, + "isis": {"type": Isis}, + "ospfv3": {"type": Ospfv3}, + "static": {"type": Static}, + "user": {"type": User}, + "_custom_data": {"type": dict}, + } + attached_host: AttachedHost + """Subclass of AvdModel.""" + bgp: Bgp + """Subclass of AvdModel.""" + connected: Connected + """Subclass of AvdModel.""" + dhcp: Dhcp + """Subclass of AvdModel.""" + dynamic: Dynamic + """Subclass of AvdModel.""" + isis: Isis + """Subclass of AvdModel.""" + ospfv3: Ospfv3 + """Subclass of AvdModel.""" + static: Static + """Subclass of AvdModel.""" + user: User + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + attached_host: AttachedHost | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + connected: Connected | UndefinedType = Undefined, + dhcp: Dhcp | UndefinedType = Undefined, + dynamic: Dynamic | UndefinedType = Undefined, + isis: Isis | UndefinedType = Undefined, + ospfv3: Ospfv3 | UndefinedType = Undefined, + static: Static | UndefinedType = Undefined, + user: User | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Redistribute. + + + Subclass of AvdModel. + + Args: + attached_host: Subclass of AvdModel. + bgp: Subclass of AvdModel. + connected: Subclass of AvdModel. + dhcp: Subclass of AvdModel. + dynamic: Subclass of AvdModel. + isis: Subclass of AvdModel. + ospfv3: Subclass of AvdModel. + static: Subclass of AvdModel. + user: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class RedistributeRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "source_protocol": {"type": str}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "rcf": {"type": str}, + "ospf_route_type": {"type": str}, + "_custom_data": {"type": dict}, + } + source_protocol: Literal["attached-host", "bgp", "connected", "dhcp", "dynamic", "isis", "ospfv3", "static", "user"] + route_map: str | None + include_leaked: bool | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only applicable if `source_protocol` is one of `connected`, + `dynamic`, `isis`, `static` and `user`. + """ + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None + """ + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospfv3'. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source_protocol: Literal["attached-host", "bgp", "connected", "dhcp", "dynamic", "isis", "ospfv3", "static", "user"] + | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] + | None + | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RedistributeRoutesItem. + + + Subclass of AvdModel. + + Args: + source_protocol: source_protocol + route_map: route_map + include_leaked: include_leaked + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only applicable if `source_protocol` is one of `connected`, + `dynamic`, `isis`, `static` and `user`. + ospf_route_type: + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospfv3'. + _custom_data: _custom_data + + """ + + class RedistributeRoutes(AvdList[RedistributeRoutesItem]): + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + + RedistributeRoutes._item_type = RedistributeRoutesItem + + _fields: ClassVar[dict] = { + "bgp": {"type": Bgp}, + "neighbors": {"type": Neighbors}, + "networks": {"type": Networks}, + "redistribute": {"type": Redistribute}, + "redistribute_routes": {"type": RedistributeRoutes}, + "_custom_data": {"type": dict}, + } + bgp: Bgp + """Subclass of AvdModel.""" + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + networks: Networks + """Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`).""" + redistribute: Redistribute + """ + Redistribute routes in to BGP. + + Subclass of AvdModel. + """ + redistribute_routes: RedistributeRoutes + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + bgp: Bgp | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + networks: Networks | UndefinedType = Undefined, + redistribute: Redistribute | UndefinedType = Undefined, + redistribute_routes: RedistributeRoutes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv6. + + + Subclass of AvdModel. + + Args: + bgp: Subclass of AvdModel. + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + networks: Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`). + redistribute: + Redistribute routes in to BGP. + + Subclass of AvdModel. + redistribute_routes: Subclass of AvdList with `RedistributeRoutesItem` items. + _custom_data: _custom_data + + """ + + class AddressFamilyIpv4Multicast(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"direction_in_action": {"type": str}, "direction_out_action": {"type": str}, "_custom_data": {"type": dict}} + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in_action: direction_in_action + direction_out_action: direction_out_action + _custom_data: _custom_data + + """ + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "_custom_data": {"type": dict}} + receive: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, receive: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: receive + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "missing_policy": {"type": MissingPolicy}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + missing_policy: MissingPolicy + """Subclass of AvdModel.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + missing_policy: MissingPolicy | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + missing_policy: Subclass of AvdModel. + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "_custom_data": {"type": dict}} + receive: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, receive: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: receive + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + ip_address: str + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class NetworksItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + prefix: str + """IPv6 prefix "A.B.C.D/E".""" + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix: str | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NetworksItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv6 prefix "A.B.C.D/E". + route_map: route_map + _custom_data: _custom_data + + """ + + class Networks(AvdIndexedList[str, NetworksItem]): + """Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`).""" + + _primary_key: ClassVar[str] = "prefix" + + Networks._item_type = NetworksItem + + class Redistribute(AvdModel): + """Subclass of AvdModel.""" + + class AttachedHost(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AttachedHost. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Connected(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Connected. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Isis(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "isis_level": {"type": str}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + isis_level: Literal["level-1", "level-2", "level-1-2"] | None + """Redistribute IS-IS route level.""" + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + isis_level: Literal["level-1", "level-2", "level-1-2"] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Isis. + + + Subclass of AvdModel. + + Args: + enabled: enabled + isis_level: Redistribute IS-IS route level. + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Ospf(AvdModel): + """Subclass of AvdModel.""" + + class MatchExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class MatchInternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchInternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class MatchNssaExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "nssa_type": {"type": int}, + "route_map": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool + nssa_type: Literal[1, 2] | None + """NSSA External Type Number.""" + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + nssa_type: Literal[1, 2] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchNssaExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + nssa_type: NSSA External Type Number. + route_map: route_map + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "match_external": {"type": MatchExternal}, + "match_internal": {"type": MatchInternal}, + "match_nssa_external": {"type": MatchNssaExternal}, + "route_map": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Redistribute OSPF routes.""" + match_external: MatchExternal + """ + Redistribute OSPF routes learned from external sources. + + Subclass of AvdModel. + """ + match_internal: MatchInternal + """ + Redistribute OSPF routes learned from internal sources. + + Subclass of AvdModel. + """ + match_nssa_external: MatchNssaExternal + """ + Redistribute OSPF routes learned from external NSSA sources. + + Subclass of AvdModel. + """ + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + match_external: MatchExternal | UndefinedType = Undefined, + match_internal: MatchInternal | UndefinedType = Undefined, + match_nssa_external: MatchNssaExternal | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospf. + + + Subclass of AvdModel. + + Args: + enabled: Redistribute OSPF routes. + match_external: + Redistribute OSPF routes learned from external sources. + + Subclass of AvdModel. + match_internal: + Redistribute OSPF routes learned from internal sources. + + Subclass of AvdModel. + match_nssa_external: + Redistribute OSPF routes learned from external NSSA sources. + + Subclass of AvdModel. + route_map: route_map + _custom_data: _custom_data + + """ + + class Ospfv3(AvdModel): + """Subclass of AvdModel.""" + + class MatchExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchInternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchInternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class MatchNssaExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "nssa_type": {"type": int}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + nssa_type: Literal[1, 2] | None + """NSSA External Type Number.""" + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + nssa_type: Literal[1, 2] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchNssaExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + nssa_type: NSSA External Type Number. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "match_external": {"type": MatchExternal}, + "match_internal": {"type": MatchInternal}, + "match_nssa_external": {"type": MatchNssaExternal}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Redistribute OSPFv3 routes.""" + match_external: MatchExternal + """ + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + """ + match_internal: MatchInternal + """ + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + """ + match_nssa_external: MatchNssaExternal + """ + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + """ + route_map: str | None + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + match_external: MatchExternal | UndefinedType = Undefined, + match_internal: MatchInternal | UndefinedType = Undefined, + match_nssa_external: MatchNssaExternal | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospfv3. + + + Subclass of AvdModel. + + Args: + enabled: Redistribute OSPFv3 routes. + match_external: + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + match_internal: + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + match_nssa_external: + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + route_map: route_map + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Static(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Static. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "attached_host": {"type": AttachedHost}, + "connected": {"type": Connected}, + "isis": {"type": Isis}, + "ospf": {"type": Ospf}, + "ospfv3": {"type": Ospfv3}, + "static": {"type": Static}, + "_custom_data": {"type": dict}, + } + attached_host: AttachedHost + """Subclass of AvdModel.""" + connected: Connected + """Subclass of AvdModel.""" + isis: Isis + """Subclass of AvdModel.""" + ospf: Ospf + """Subclass of AvdModel.""" + ospfv3: Ospfv3 + """Subclass of AvdModel.""" + static: Static + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + attached_host: AttachedHost | UndefinedType = Undefined, + connected: Connected | UndefinedType = Undefined, + isis: Isis | UndefinedType = Undefined, + ospf: Ospf | UndefinedType = Undefined, + ospfv3: Ospfv3 | UndefinedType = Undefined, + static: Static | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Redistribute. + + + Subclass of AvdModel. + + Args: + attached_host: Subclass of AvdModel. + connected: Subclass of AvdModel. + isis: Subclass of AvdModel. + ospf: Subclass of AvdModel. + ospfv3: Subclass of AvdModel. + static: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class RedistributeRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "source_protocol": {"type": str}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "rcf": {"type": str}, + "ospf_route_type": {"type": str}, + "_custom_data": {"type": dict}, + } + source_protocol: Literal["attached-host", "connected", "isis", "ospf", "ospfv3", "static"] + route_map: str | None + include_leaked: bool | None + """Only applicable if `source_protocol` is `isis`.""" + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only applicable if `source_protocol` is `isis`. + """ + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None + """ + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospf' and + 'ospfv3'. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source_protocol: Literal["attached-host", "connected", "isis", "ospf", "ospfv3", "static"] | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] + | None + | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RedistributeRoutesItem. + + + Subclass of AvdModel. + + Args: + source_protocol: source_protocol + route_map: route_map + include_leaked: Only applicable if `source_protocol` is `isis`. + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only applicable if `source_protocol` is `isis`. + ospf_route_type: + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospf' and + 'ospfv3'. + _custom_data: _custom_data + + """ + + class RedistributeRoutes(AvdList[RedistributeRoutesItem]): + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + + RedistributeRoutes._item_type = RedistributeRoutesItem + + _fields: ClassVar[dict] = { + "bgp": {"type": Bgp}, + "neighbors": {"type": Neighbors}, + "networks": {"type": Networks}, + "redistribute": {"type": Redistribute}, + "redistribute_routes": {"type": RedistributeRoutes}, + "_custom_data": {"type": dict}, + } + bgp: Bgp + """Subclass of AvdModel.""" + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + networks: Networks + """Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`).""" + redistribute: Redistribute + """ + Redistribute routes in to BGP. + + Subclass of AvdModel. + """ + redistribute_routes: RedistributeRoutes + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + bgp: Bgp | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + networks: Networks | UndefinedType = Undefined, + redistribute: Redistribute | UndefinedType = Undefined, + redistribute_routes: RedistributeRoutes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv4Multicast. + + + Subclass of AvdModel. + + Args: + bgp: Subclass of AvdModel. + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + networks: Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`). + redistribute: + Redistribute routes in to BGP. + + Subclass of AvdModel. + redistribute_routes: Subclass of AvdList with `RedistributeRoutesItem` items. + _custom_data: _custom_data + + """ + + class AddressFamilyIpv6Multicast(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"direction_in_action": {"type": str}, "direction_out_action": {"type": str}, "_custom_data": {"type": dict}} + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in_action: direction_in_action + direction_out_action: direction_out_action + _custom_data: _custom_data + + """ + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "_custom_data": {"type": dict}} + receive: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, receive: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: receive + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "missing_policy": {"type": MissingPolicy}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + missing_policy: MissingPolicy + """Subclass of AvdModel.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + missing_policy: MissingPolicy | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + missing_policy: Subclass of AvdModel. + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + class AdditionalPaths(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"receive": {"type": bool}, "_custom_data": {"type": dict}} + receive: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, receive: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + AdditionalPaths. + + + Subclass of AvdModel. + + Args: + receive: receive + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "additional_paths": {"type": AdditionalPaths}, + "_custom_data": {"type": dict}, + } + ip_address: str + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + additional_paths: AdditionalPaths + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + additional_paths: AdditionalPaths | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + additional_paths: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + class NetworksItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + prefix: str + """IPv6 prefix "A:B:C:D:E:F:G:H/I".""" + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix: str | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NetworksItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv6 prefix "A:B:C:D:E:F:G:H/I". + route_map: route_map + _custom_data: _custom_data + + """ + + class Networks(AvdIndexedList[str, NetworksItem]): + """Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`).""" + + _primary_key: ClassVar[str] = "prefix" + + Networks._item_type = NetworksItem + + class Redistribute(AvdModel): + """Subclass of AvdModel.""" + + class Connected(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Connected. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class Isis(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "isis_level": {"type": str}, + "route_map": {"type": str}, + "rcf": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + isis_level: Literal["level-1", "level-2", "level-1-2"] | None + """Redistribute IS-IS route level.""" + route_map: str | None + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + """ + include_leaked: bool | None + """Include following routes while redistributing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + isis_level: Literal["level-1", "level-2", "level-1-2"] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Isis. + + + Subclass of AvdModel. + + Args: + enabled: enabled + isis_level: Redistribute IS-IS route level. + route_map: route_map + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + include_leaked: Include following routes while redistributing. + _custom_data: _custom_data + + """ + + class Ospf(AvdModel): + """Subclass of AvdModel.""" + + class MatchExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class MatchInternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchInternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class MatchNssaExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "nssa_type": {"type": int}, + "route_map": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool + nssa_type: Literal[1, 2] | None + """NSSA External Type Number.""" + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + nssa_type: Literal[1, 2] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchNssaExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + nssa_type: NSSA External Type Number. + route_map: route_map + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "match_external": {"type": MatchExternal}, + "match_internal": {"type": MatchInternal}, + "match_nssa_external": {"type": MatchNssaExternal}, + "route_map": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Redistribute OSPF routes.""" + match_external: MatchExternal + """ + Redistribute OSPF routes learned from external sources. + + Subclass of AvdModel. + """ + match_internal: MatchInternal + """ + Redistribute OSPF routes learned from internal sources. + + Subclass of AvdModel. + """ + match_nssa_external: MatchNssaExternal + """ + Redistribute OSPF routes learned from external NSSA sources. + + Subclass of AvdModel. + """ + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + match_external: MatchExternal | UndefinedType = Undefined, + match_internal: MatchInternal | UndefinedType = Undefined, + match_nssa_external: MatchNssaExternal | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospf. + + + Subclass of AvdModel. + + Args: + enabled: Redistribute OSPF routes. + match_external: + Redistribute OSPF routes learned from external sources. + + Subclass of AvdModel. + match_internal: + Redistribute OSPF routes learned from internal sources. + + Subclass of AvdModel. + match_nssa_external: + Redistribute OSPF routes learned from external NSSA sources. + + Subclass of AvdModel. + route_map: route_map + _custom_data: _custom_data + + """ + + class Ospfv3(AvdModel): + """Subclass of AvdModel.""" + + class MatchExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class MatchInternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchInternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + class MatchNssaExternal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "nssa_type": {"type": int}, + "route_map": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool + nssa_type: Literal[1, 2] | None + """NSSA External Type Number.""" + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + nssa_type: Literal[1, 2] | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchNssaExternal. + + + Subclass of AvdModel. + + Args: + enabled: enabled + nssa_type: NSSA External Type Number. + route_map: route_map + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "match_external": {"type": MatchExternal}, + "match_internal": {"type": MatchInternal}, + "match_nssa_external": {"type": MatchNssaExternal}, + "route_map": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Redistribute OSPFv3 routes.""" + match_external: MatchExternal + """ + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + """ + match_internal: MatchInternal + """ + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + """ + match_nssa_external: MatchNssaExternal + """ + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + """ + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + match_external: MatchExternal | UndefinedType = Undefined, + match_internal: MatchInternal | UndefinedType = Undefined, + match_nssa_external: MatchNssaExternal | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospfv3. + + + Subclass of AvdModel. + + Args: + enabled: Redistribute OSPFv3 routes. + match_external: + Redistribute OSPFv3 routes learned from external sources. + + Subclass of AvdModel. + match_internal: + Redistribute OSPFv3 routes learned from internal sources. + + Subclass of AvdModel. + match_nssa_external: + Redistribute OSPFv3 routes learned from external NSSA sources. + + Subclass of AvdModel. + route_map: route_map + _custom_data: _custom_data + + """ + + class Static(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Static. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: route_map + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "connected": {"type": Connected}, + "isis": {"type": Isis}, + "ospf": {"type": Ospf}, + "ospfv3": {"type": Ospfv3}, + "static": {"type": Static}, + "_custom_data": {"type": dict}, + } + connected: Connected + """Subclass of AvdModel.""" + isis: Isis + """Subclass of AvdModel.""" + ospf: Ospf + """Subclass of AvdModel.""" + ospfv3: Ospfv3 + """Subclass of AvdModel.""" + static: Static + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + connected: Connected | UndefinedType = Undefined, + isis: Isis | UndefinedType = Undefined, + ospf: Ospf | UndefinedType = Undefined, + ospfv3: Ospfv3 | UndefinedType = Undefined, + static: Static | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Redistribute. + + + Subclass of AvdModel. + + Args: + connected: Subclass of AvdModel. + isis: Subclass of AvdModel. + ospf: Subclass of AvdModel. + ospfv3: Subclass of AvdModel. + static: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class RedistributeRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "source_protocol": {"type": str}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "rcf": {"type": str}, + "ospf_route_type": {"type": str}, + "_custom_data": {"type": dict}, + } + source_protocol: Literal["connected", "isis", "ospf", "ospfv3", "static"] + route_map: str | None + include_leaked: bool | None + """Only applicable if `source_protocol` is `isis`.""" + rcf: str | None + """ + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only applicable if `source_protocol` is `isis`. + """ + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] | None + """ + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospf' and + 'ospfv3'. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source_protocol: Literal["connected", "isis", "ospf", "ospfv3", "static"] | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + ospf_route_type: Literal["external", "internal", "nssa-external", "nssa-external 1", "nssa-external 2"] + | None + | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RedistributeRoutesItem. + + + Subclass of AvdModel. + + Args: + source_protocol: source_protocol + route_map: route_map + include_leaked: Only applicable if `source_protocol` is `isis`. + rcf: + RCF function name with parenthesis. + Example: MyFunction(myarg). + `route_map` and `rcf` are mutually + exclusive. `route_map` takes precedence. + Only applicable if `source_protocol` is `isis`. + ospf_route_type: + Routes learned by the OSPF protocol. + The `ospf_route_type` is valid for source_protocols 'ospf' and + 'ospfv3'. + _custom_data: _custom_data + + """ + + class RedistributeRoutes(AvdList[RedistributeRoutesItem]): + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + + RedistributeRoutes._item_type = RedistributeRoutesItem + + _fields: ClassVar[dict] = { + "bgp": {"type": Bgp}, + "neighbors": {"type": Neighbors}, + "networks": {"type": Networks}, + "redistribute": {"type": Redistribute}, + "redistribute_routes": {"type": RedistributeRoutes}, + "_custom_data": {"type": dict}, + } + bgp: Bgp + """Subclass of AvdModel.""" + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + networks: Networks + """Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`).""" + redistribute: Redistribute + """ + Redistribute routes in to BGP. + + Subclass of AvdModel. + """ + redistribute_routes: RedistributeRoutes + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + bgp: Bgp | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + networks: Networks | UndefinedType = Undefined, + redistribute: Redistribute | UndefinedType = Undefined, + redistribute_routes: RedistributeRoutes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv6Multicast. + + + Subclass of AvdModel. + + Args: + bgp: Subclass of AvdModel. + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + networks: Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`). + redistribute: + Redistribute routes in to BGP. + + Subclass of AvdModel. + redistribute_routes: Subclass of AvdList with `RedistributeRoutesItem` items. + _custom_data: _custom_data + + """ + + class AddressFamilyFlowSpecIpv4(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"direction_in_action": {"type": str}, "direction_out_action": {"type": str}, "_custom_data": {"type": dict}} + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in_action: direction_in_action + direction_out_action: direction_out_action + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"missing_policy": {"type": MissingPolicy}, "_custom_data": {"type": dict}} + missing_policy: MissingPolicy + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, missing_policy: MissingPolicy | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + missing_policy: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ip_address": {"type": str}, "activate": {"type": bool}, "_custom_data": {"type": dict}} + ip_address: str + activate: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + _fields: ClassVar[dict] = {"bgp": {"type": Bgp}, "neighbors": {"type": Neighbors}, "_custom_data": {"type": dict}} + bgp: Bgp + """Subclass of AvdModel.""" + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + bgp: Bgp | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyFlowSpecIpv4. + + + Subclass of AvdModel. + + Args: + bgp: Subclass of AvdModel. + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + _custom_data: _custom_data + + """ + + class AddressFamilyFlowSpecIpv6(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"direction_in_action": {"type": str}, "direction_out_action": {"type": str}, "_custom_data": {"type": dict}} + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + direction_out_action: Literal["deny", "deny-in-out", "permit"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in_action: direction_in_action + direction_out_action: direction_out_action + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"missing_policy": {"type": MissingPolicy}, "_custom_data": {"type": dict}} + missing_policy: MissingPolicy + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, missing_policy: MissingPolicy | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + missing_policy: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class NeighborsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ip_address": {"type": str}, "activate": {"type": bool}, "_custom_data": {"type": dict}} + ip_address: str + activate: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + activate: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NeighborsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + activate: activate + _custom_data: _custom_data + + """ + + class Neighbors(AvdIndexedList[str, NeighborsItem]): + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + Neighbors._item_type = NeighborsItem + + _fields: ClassVar[dict] = {"bgp": {"type": Bgp}, "neighbors": {"type": Neighbors}, "_custom_data": {"type": dict}} + bgp: Bgp + """Subclass of AvdModel.""" + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + bgp: Bgp | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyFlowSpecIpv6. + + + Subclass of AvdModel. + + Args: + bgp: Subclass of AvdModel. + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "bgp": {"type": Bgp}, + "rd": {"type": str}, + "evpn_multicast": {"type": bool}, + "evpn_multicast_address_family": {"type": EvpnMulticastAddressFamily}, + "evpn_multicast_gateway_dr_election": {"type": EvpnMulticastGatewayDrElection}, + "default_route_exports": {"type": DefaultRouteExports}, + "route_targets": {"type": RouteTargets}, + "router_id": {"type": str}, + "timers": {"type": str}, + "networks": {"type": Networks}, + "maximum_paths": {"type": MaximumPaths}, + "updates": {"type": Updates}, + "listen_ranges": {"type": ListenRanges}, + "neighbors": {"type": Neighbors}, + "neighbor_interfaces": {"type": NeighborInterfaces}, + "redistribute": {"type": Redistribute}, + "redistribute_routes": {"type": RedistributeRoutes}, + "aggregate_addresses": {"type": AggregateAddresses}, + "address_family_ipv4": {"type": AddressFamilyIpv4}, + "address_family_ipv6": {"type": AddressFamilyIpv6}, + "address_family_ipv4_multicast": {"type": AddressFamilyIpv4Multicast}, + "address_family_ipv6_multicast": {"type": AddressFamilyIpv6Multicast}, + "address_family_flow_spec_ipv4": {"type": AddressFamilyFlowSpecIpv4}, + "address_family_flow_spec_ipv6": {"type": AddressFamilyFlowSpecIpv6}, + "eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """VRF name.""" + bgp: Bgp + """Subclass of AvdModel.""" + rd: str | None + """Route distinguisher.""" + evpn_multicast: bool | None + evpn_multicast_address_family: EvpnMulticastAddressFamily + """ + Enable per-AF EVPN multicast settings. + + Subclass of AvdModel. + """ + evpn_multicast_gateway_dr_election: EvpnMulticastGatewayDrElection + """Subclass of AvdModel.""" + default_route_exports: DefaultRouteExports + """ + Enable default-originate per VRF/address-family. + + Subclass of AvdIndexedList with + `DefaultRouteExportsItem` items. Primary key is `address_family` (`str`). + """ + route_targets: RouteTargets + """Subclass of AvdModel.""" + router_id: str | None + """in IP address format A.B.C.D.""" + timers: str | None + """BGP Keepalive and Hold Timer values in seconds as string "<0-3600> <0-3600>".""" + networks: Networks + """Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`).""" + maximum_paths: MaximumPaths + """Subclass of AvdModel.""" + updates: Updates + """Subclass of AvdModel.""" + listen_ranges: ListenRanges + """ + Improved "listen_ranges" data model to support multiple listen ranges and additional filter + capabilities. + + + Subclass of AvdList with `ListenRangesItem` items. + """ + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + neighbor_interfaces: NeighborInterfaces + """Subclass of AvdIndexedList with `NeighborInterfacesItem` items. Primary key is `name` (`str`).""" + redistribute: Redistribute + """ + Redistribute routes in to BGP. + + Subclass of AvdModel. + """ + redistribute_routes: RedistributeRoutes + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + aggregate_addresses: AggregateAddresses + """Subclass of AvdIndexedList with `AggregateAddressesItem` items. Primary key is `prefix` (`str`).""" + address_family_ipv4: AddressFamilyIpv4 + """Subclass of AvdModel.""" + address_family_ipv6: AddressFamilyIpv6 + """Subclass of AvdModel.""" + address_family_ipv4_multicast: AddressFamilyIpv4Multicast + """Subclass of AvdModel.""" + address_family_ipv6_multicast: AddressFamilyIpv6Multicast + """Subclass of AvdModel.""" + address_family_flow_spec_ipv4: AddressFamilyFlowSpecIpv4 + """Subclass of AvdModel.""" + address_family_flow_spec_ipv6: AddressFamilyFlowSpecIpv6 + """Subclass of AvdModel.""" + eos_cli: str | None + """ + Multiline EOS CLI rendered directly on the Router BGP, VRF definition in the final EOS + configuration. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + rd: str | None | UndefinedType = Undefined, + evpn_multicast: bool | None | UndefinedType = Undefined, + evpn_multicast_address_family: EvpnMulticastAddressFamily | UndefinedType = Undefined, + evpn_multicast_gateway_dr_election: EvpnMulticastGatewayDrElection | UndefinedType = Undefined, + default_route_exports: DefaultRouteExports | UndefinedType = Undefined, + route_targets: RouteTargets | UndefinedType = Undefined, + router_id: str | None | UndefinedType = Undefined, + timers: str | None | UndefinedType = Undefined, + networks: Networks | UndefinedType = Undefined, + maximum_paths: MaximumPaths | UndefinedType = Undefined, + updates: Updates | UndefinedType = Undefined, + listen_ranges: ListenRanges | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + neighbor_interfaces: NeighborInterfaces | UndefinedType = Undefined, + redistribute: Redistribute | UndefinedType = Undefined, + redistribute_routes: RedistributeRoutes | UndefinedType = Undefined, + aggregate_addresses: AggregateAddresses | UndefinedType = Undefined, + address_family_ipv4: AddressFamilyIpv4 | UndefinedType = Undefined, + address_family_ipv6: AddressFamilyIpv6 | UndefinedType = Undefined, + address_family_ipv4_multicast: AddressFamilyIpv4Multicast | UndefinedType = Undefined, + address_family_ipv6_multicast: AddressFamilyIpv6Multicast | UndefinedType = Undefined, + address_family_flow_spec_ipv4: AddressFamilyFlowSpecIpv4 | UndefinedType = Undefined, + address_family_flow_spec_ipv6: AddressFamilyFlowSpecIpv6 | UndefinedType = Undefined, + eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: VRF name. + bgp: Subclass of AvdModel. + rd: Route distinguisher. + evpn_multicast: evpn_multicast + evpn_multicast_address_family: + Enable per-AF EVPN multicast settings. + + Subclass of AvdModel. + evpn_multicast_gateway_dr_election: Subclass of AvdModel. + default_route_exports: + Enable default-originate per VRF/address-family. + + Subclass of AvdIndexedList with + `DefaultRouteExportsItem` items. Primary key is `address_family` (`str`). + route_targets: Subclass of AvdModel. + router_id: in IP address format A.B.C.D. + timers: BGP Keepalive and Hold Timer values in seconds as string "<0-3600> <0-3600>". + networks: Subclass of AvdIndexedList with `NetworksItem` items. Primary key is `prefix` (`str`). + maximum_paths: Subclass of AvdModel. + updates: Subclass of AvdModel. + listen_ranges: + Improved "listen_ranges" data model to support multiple listen ranges and additional filter + capabilities. + + + Subclass of AvdList with `ListenRangesItem` items. + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + neighbor_interfaces: Subclass of AvdIndexedList with `NeighborInterfacesItem` items. Primary key is `name` (`str`). + redistribute: + Redistribute routes in to BGP. + + Subclass of AvdModel. + redistribute_routes: Subclass of AvdList with `RedistributeRoutesItem` items. + aggregate_addresses: Subclass of AvdIndexedList with `AggregateAddressesItem` items. Primary key is `prefix` (`str`). + address_family_ipv4: Subclass of AvdModel. + address_family_ipv6: Subclass of AvdModel. + address_family_ipv4_multicast: Subclass of AvdModel. + address_family_ipv6_multicast: Subclass of AvdModel. + address_family_flow_spec_ipv4: Subclass of AvdModel. + address_family_flow_spec_ipv6: Subclass of AvdModel. + eos_cli: + Multiline EOS CLI rendered directly on the Router BGP, VRF definition in the final EOS + configuration. + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + class SessionTrackersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "recovery_delay": {"type": int}, "_custom_data": {"type": dict}} + name: str + """Name of session tracker.""" + recovery_delay: int | None + """Recovery delay in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + recovery_delay: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SessionTrackersItem. + + + Subclass of AvdModel. + + Args: + name: Name of session tracker. + recovery_delay: Recovery delay in seconds. + _custom_data: _custom_data + + """ + + class SessionTrackers(AvdIndexedList[str, SessionTrackersItem]): + """Subclass of AvdIndexedList with `SessionTrackersItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + SessionTrackers._item_type = SessionTrackersItem + + _fields: ClassVar[dict] = { + "field_as": {"type": str}, + "as_notation": {"type": str}, + "router_id": {"type": str}, + "timers": {"type": Timers}, + "distance": {"type": Distance}, + "graceful_restart": {"type": GracefulRestart}, + "graceful_restart_helper": {"type": GracefulRestartHelper}, + "maximum_paths": {"type": MaximumPaths}, + "updates": {"type": Updates}, + "bgp_cluster_id": {"type": str}, + "bgp_defaults": {"type": BgpDefaults}, + "bgp": {"type": Bgp}, + "listen_ranges": {"type": ListenRanges}, + "neighbor_default": {"type": NeighborDefault}, + "peer_groups": {"type": PeerGroups}, + "neighbors": {"type": Neighbors}, + "neighbor_interfaces": {"type": NeighborInterfaces}, + "aggregate_addresses": {"type": AggregateAddresses}, + "redistribute": {"type": Redistribute}, + "redistribute_routes": {"type": RedistributeRoutes}, + "vlan_aware_bundles": {"type": VlanAwareBundles}, + "vlans": {"type": Vlans}, + "vpws": {"type": Vpws}, + "address_family_evpn": {"type": AddressFamilyEvpn}, + "address_family_rtc": {"type": AddressFamilyRtc}, + "address_family_ipv4": {"type": AddressFamilyIpv4}, + "address_family_ipv4_labeled_unicast": {"type": AddressFamilyIpv4LabeledUnicast}, + "address_family_ipv4_multicast": {"type": AddressFamilyIpv4Multicast}, + "address_family_ipv4_sr_te": {"type": AddressFamilyIpv4SrTe}, + "address_family_ipv6": {"type": AddressFamilyIpv6}, + "address_family_ipv6_multicast": {"type": AddressFamilyIpv6Multicast}, + "address_family_ipv6_sr_te": {"type": AddressFamilyIpv6SrTe}, + "address_family_link_state": {"type": AddressFamilyLinkState}, + "address_family_flow_spec_ipv4": {"type": AddressFamilyFlowSpecIpv4}, + "address_family_flow_spec_ipv6": {"type": AddressFamilyFlowSpecIpv6}, + "address_family_path_selection": {"type": AddressFamilyPathSelection}, + "address_family_vpn_ipv4": {"type": AddressFamilyVpnIpv4}, + "address_family_vpn_ipv6": {"type": AddressFamilyVpnIpv6}, + "vrfs": {"type": Vrfs}, + "session_trackers": {"type": SessionTrackers}, + "eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + _field_to_key_map: ClassVar[dict] = {"field_as": "as"} + _key_to_field_map: ClassVar[dict] = {"as": "field_as"} + field_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + as_notation: Literal["asdot", "asplain"] | None + """ + BGP AS can be deplayed in the asplain <1-4294967295> or asdot notation "<1-65535>.<0-65535>". This + flag indicates which mode is preferred - asplain is the default. + """ + router_id: str | None + """In IP address format A.B.C.D.""" + timers: Timers + """Subclass of AvdModel.""" + distance: Distance + """Subclass of AvdModel.""" + graceful_restart: GracefulRestart + """Subclass of AvdModel.""" + graceful_restart_helper: GracefulRestartHelper + """Subclass of AvdModel.""" + maximum_paths: MaximumPaths + """Subclass of AvdModel.""" + updates: Updates + """Subclass of AvdModel.""" + bgp_cluster_id: str | None + """IP Address A.B.C.D.""" + bgp_defaults: BgpDefaults + """ + BGP command as string. + + Subclass of AvdList with `str` items. + """ + bgp: Bgp + """Subclass of AvdModel.""" + listen_ranges: ListenRanges + """ + Improved "listen_ranges" data model to support multiple listen ranges and additional filter + capabilities. + + + Subclass of AvdList with `ListenRangesItem` items. + """ + neighbor_default: NeighborDefault + """Subclass of AvdModel.""" + peer_groups: PeerGroups + """Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`).""" + neighbors: Neighbors + """Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`).""" + neighbor_interfaces: NeighborInterfaces + """Subclass of AvdIndexedList with `NeighborInterfacesItem` items. Primary key is `name` (`str`).""" + aggregate_addresses: AggregateAddresses + """Subclass of AvdIndexedList with `AggregateAddressesItem` items. Primary key is `prefix` (`str`).""" + redistribute: Redistribute + """ + Redistribute routes in to BGP. + + Subclass of AvdModel. + """ + redistribute_routes: RedistributeRoutes + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + vlan_aware_bundles: VlanAwareBundles + """Subclass of AvdIndexedList with `VlanAwareBundlesItem` items. Primary key is `name` (`str`).""" + vlans: Vlans + """Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`int`).""" + vpws: Vpws + """Subclass of AvdIndexedList with `VpwsItem` items. Primary key is `name` (`str`).""" + address_family_evpn: AddressFamilyEvpn + """Subclass of AvdModel.""" + address_family_rtc: AddressFamilyRtc + """Subclass of AvdModel.""" + address_family_ipv4: AddressFamilyIpv4 + """Subclass of AvdModel.""" + address_family_ipv4_labeled_unicast: AddressFamilyIpv4LabeledUnicast + """Subclass of AvdModel.""" + address_family_ipv4_multicast: AddressFamilyIpv4Multicast + """Subclass of AvdModel.""" + address_family_ipv4_sr_te: AddressFamilyIpv4SrTe + """Subclass of AvdModel.""" + address_family_ipv6: AddressFamilyIpv6 + """Subclass of AvdModel.""" + address_family_ipv6_multicast: AddressFamilyIpv6Multicast + """Subclass of AvdModel.""" + address_family_ipv6_sr_te: AddressFamilyIpv6SrTe + """Subclass of AvdModel.""" + address_family_link_state: AddressFamilyLinkState + """Subclass of AvdModel.""" + address_family_flow_spec_ipv4: AddressFamilyFlowSpecIpv4 + """Subclass of AvdModel.""" + address_family_flow_spec_ipv6: AddressFamilyFlowSpecIpv6 + """Subclass of AvdModel.""" + address_family_path_selection: AddressFamilyPathSelection + """Subclass of AvdModel.""" + address_family_vpn_ipv4: AddressFamilyVpnIpv4 + """Subclass of AvdModel.""" + address_family_vpn_ipv6: AddressFamilyVpnIpv6 + """Subclass of AvdModel.""" + vrfs: Vrfs + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + session_trackers: SessionTrackers + """Subclass of AvdIndexedList with `SessionTrackersItem` items. Primary key is `name` (`str`).""" + eos_cli: str | None + """Multiline EOS CLI rendered directly on the Router BGP in the final EOS configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + field_as: str | None | UndefinedType = Undefined, + as_notation: Literal["asdot", "asplain"] | None | UndefinedType = Undefined, + router_id: str | None | UndefinedType = Undefined, + timers: Timers | UndefinedType = Undefined, + distance: Distance | UndefinedType = Undefined, + graceful_restart: GracefulRestart | UndefinedType = Undefined, + graceful_restart_helper: GracefulRestartHelper | UndefinedType = Undefined, + maximum_paths: MaximumPaths | UndefinedType = Undefined, + updates: Updates | UndefinedType = Undefined, + bgp_cluster_id: str | None | UndefinedType = Undefined, + bgp_defaults: BgpDefaults | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + listen_ranges: ListenRanges | UndefinedType = Undefined, + neighbor_default: NeighborDefault | UndefinedType = Undefined, + peer_groups: PeerGroups | UndefinedType = Undefined, + neighbors: Neighbors | UndefinedType = Undefined, + neighbor_interfaces: NeighborInterfaces | UndefinedType = Undefined, + aggregate_addresses: AggregateAddresses | UndefinedType = Undefined, + redistribute: Redistribute | UndefinedType = Undefined, + redistribute_routes: RedistributeRoutes | UndefinedType = Undefined, + vlan_aware_bundles: VlanAwareBundles | UndefinedType = Undefined, + vlans: Vlans | UndefinedType = Undefined, + vpws: Vpws | UndefinedType = Undefined, + address_family_evpn: AddressFamilyEvpn | UndefinedType = Undefined, + address_family_rtc: AddressFamilyRtc | UndefinedType = Undefined, + address_family_ipv4: AddressFamilyIpv4 | UndefinedType = Undefined, + address_family_ipv4_labeled_unicast: AddressFamilyIpv4LabeledUnicast | UndefinedType = Undefined, + address_family_ipv4_multicast: AddressFamilyIpv4Multicast | UndefinedType = Undefined, + address_family_ipv4_sr_te: AddressFamilyIpv4SrTe | UndefinedType = Undefined, + address_family_ipv6: AddressFamilyIpv6 | UndefinedType = Undefined, + address_family_ipv6_multicast: AddressFamilyIpv6Multicast | UndefinedType = Undefined, + address_family_ipv6_sr_te: AddressFamilyIpv6SrTe | UndefinedType = Undefined, + address_family_link_state: AddressFamilyLinkState | UndefinedType = Undefined, + address_family_flow_spec_ipv4: AddressFamilyFlowSpecIpv4 | UndefinedType = Undefined, + address_family_flow_spec_ipv6: AddressFamilyFlowSpecIpv6 | UndefinedType = Undefined, + address_family_path_selection: AddressFamilyPathSelection | UndefinedType = Undefined, + address_family_vpn_ipv4: AddressFamilyVpnIpv4 | UndefinedType = Undefined, + address_family_vpn_ipv6: AddressFamilyVpnIpv6 | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + session_trackers: SessionTrackers | UndefinedType = Undefined, + eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouterBgp. + + + Subclass of AvdModel. + + Args: + field_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + as_notation: + BGP AS can be deplayed in the asplain <1-4294967295> or asdot notation "<1-65535>.<0-65535>". This + flag indicates which mode is preferred - asplain is the default. + router_id: In IP address format A.B.C.D. + timers: Subclass of AvdModel. + distance: Subclass of AvdModel. + graceful_restart: Subclass of AvdModel. + graceful_restart_helper: Subclass of AvdModel. + maximum_paths: Subclass of AvdModel. + updates: Subclass of AvdModel. + bgp_cluster_id: IP Address A.B.C.D. + bgp_defaults: + BGP command as string. + + Subclass of AvdList with `str` items. + bgp: Subclass of AvdModel. + listen_ranges: + Improved "listen_ranges" data model to support multiple listen ranges and additional filter + capabilities. + + + Subclass of AvdList with `ListenRangesItem` items. + neighbor_default: Subclass of AvdModel. + peer_groups: Subclass of AvdIndexedList with `PeerGroupsItem` items. Primary key is `name` (`str`). + neighbors: Subclass of AvdIndexedList with `NeighborsItem` items. Primary key is `ip_address` (`str`). + neighbor_interfaces: Subclass of AvdIndexedList with `NeighborInterfacesItem` items. Primary key is `name` (`str`). + aggregate_addresses: Subclass of AvdIndexedList with `AggregateAddressesItem` items. Primary key is `prefix` (`str`). + redistribute: + Redistribute routes in to BGP. + + Subclass of AvdModel. + redistribute_routes: Subclass of AvdList with `RedistributeRoutesItem` items. + vlan_aware_bundles: Subclass of AvdIndexedList with `VlanAwareBundlesItem` items. Primary key is `name` (`str`). + vlans: Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`int`). + vpws: Subclass of AvdIndexedList with `VpwsItem` items. Primary key is `name` (`str`). + address_family_evpn: Subclass of AvdModel. + address_family_rtc: Subclass of AvdModel. + address_family_ipv4: Subclass of AvdModel. + address_family_ipv4_labeled_unicast: Subclass of AvdModel. + address_family_ipv4_multicast: Subclass of AvdModel. + address_family_ipv4_sr_te: Subclass of AvdModel. + address_family_ipv6: Subclass of AvdModel. + address_family_ipv6_multicast: Subclass of AvdModel. + address_family_ipv6_sr_te: Subclass of AvdModel. + address_family_link_state: Subclass of AvdModel. + address_family_flow_spec_ipv4: Subclass of AvdModel. + address_family_flow_spec_ipv6: Subclass of AvdModel. + address_family_path_selection: Subclass of AvdModel. + address_family_vpn_ipv4: Subclass of AvdModel. + address_family_vpn_ipv6: Subclass of AvdModel. + vrfs: Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`). + session_trackers: Subclass of AvdIndexedList with `SessionTrackersItem` items. Primary key is `name` (`str`). + eos_cli: Multiline EOS CLI rendered directly on the Router BGP in the final EOS configuration. + _custom_data: _custom_data + + """ + + class RouterGeneral(AvdModel): + """Subclass of AvdModel.""" + + class RouterId(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4": {"type": str}, "ipv6": {"type": str}, "_custom_data": {"type": dict}} + ipv4: str | None + """IPv4 Address.""" + ipv6: str | None + """IPv6 Address.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4: str | None | UndefinedType = Undefined, + ipv6: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouterId. + + + Subclass of AvdModel. + + Args: + ipv4: IPv4 Address. + ipv6: IPv6 Address. + _custom_data: _custom_data + + """ + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + class LeakRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"source_vrf": {"type": str}, "subscribe_policy": {"type": str}, "_custom_data": {"type": dict}} + source_vrf: str | None + subscribe_policy: str | None + """Route-Map Policy.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source_vrf: str | None | UndefinedType = Undefined, + subscribe_policy: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LeakRoutesItem. + + + Subclass of AvdModel. + + Args: + source_vrf: source_vrf + subscribe_policy: Route-Map Policy. + _custom_data: _custom_data + + """ + + class LeakRoutes(AvdList[LeakRoutesItem]): + """Subclass of AvdList with `LeakRoutesItem` items.""" + + LeakRoutes._item_type = LeakRoutesItem + + class Routes(AvdModel): + """Subclass of AvdModel.""" + + class DynamicPrefixListsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + """Dynamic Prefix List Name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, name: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + DynamicPrefixListsItem. + + + Subclass of AvdModel. + + Args: + name: Dynamic Prefix List Name. + _custom_data: _custom_data + + """ + + class DynamicPrefixLists(AvdList[DynamicPrefixListsItem]): + """Subclass of AvdList with `DynamicPrefixListsItem` items.""" + + DynamicPrefixLists._item_type = DynamicPrefixListsItem + + _fields: ClassVar[dict] = {"dynamic_prefix_lists": {"type": DynamicPrefixLists}, "_custom_data": {"type": dict}} + dynamic_prefix_lists: DynamicPrefixLists + """Subclass of AvdList with `DynamicPrefixListsItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, dynamic_prefix_lists: DynamicPrefixLists | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Routes. + + + Subclass of AvdModel. + + Args: + dynamic_prefix_lists: Subclass of AvdList with `DynamicPrefixListsItem` items. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"name": {"type": str}, "leak_routes": {"type": LeakRoutes}, "routes": {"type": Routes}, "_custom_data": {"type": dict}} + name: str + """Destination-VRF.""" + leak_routes: LeakRoutes + """Subclass of AvdList with `LeakRoutesItem` items.""" + routes: Routes + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + leak_routes: LeakRoutes | UndefinedType = Undefined, + routes: Routes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: Destination-VRF. + leak_routes: Subclass of AvdList with `LeakRoutesItem` items. + routes: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + class ControlFunctions(AvdModel): + """Subclass of AvdModel.""" + + class CodeUnitsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "content": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Name of the code unit.""" + content: str + """ + Content of route control function. + e.g. + function ACCEPT_ALL() { + return true; + } + EOF + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + content: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CodeUnitsItem. + + + Subclass of AvdModel. + + Args: + name: Name of the code unit. + content: + Content of route control function. + e.g. + function ACCEPT_ALL() { + return true; + } + EOF + _custom_data: _custom_data + + """ + + class CodeUnits(AvdIndexedList[str, CodeUnitsItem]): + """Subclass of AvdIndexedList with `CodeUnitsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + CodeUnits._item_type = CodeUnitsItem + + _fields: ClassVar[dict] = {"code_units": {"type": CodeUnits}, "_custom_data": {"type": dict}} + code_units: CodeUnits + """Subclass of AvdIndexedList with `CodeUnitsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, code_units: CodeUnits | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + ControlFunctions. + + + Subclass of AvdModel. + + Args: + code_units: Subclass of AvdIndexedList with `CodeUnitsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "router_id": {"type": RouterId}, + "nexthop_fast_failover": {"type": bool, "default": False}, + "vrfs": {"type": Vrfs}, + "control_functions": {"type": ControlFunctions}, + "_custom_data": {"type": dict}, + } + router_id: RouterId + """Subclass of AvdModel.""" + nexthop_fast_failover: bool + """Default value: `False`""" + vrfs: Vrfs + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + control_functions: ControlFunctions + """ + Routing control functions (RCF) used to filter and update routes from a peer or during + redistributions. + Warning: + This configuration cannot be pushed with `eos_config_deploy_eapi`, because + of limitations in `arista.eos` and `ansible.netcommon` plugins. + The configuration can be pushed via + CloudVision with `eos_config_deploy_cvp` or `cv_deploy`. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + router_id: RouterId | UndefinedType = Undefined, + nexthop_fast_failover: bool | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + control_functions: ControlFunctions | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouterGeneral. + + + Subclass of AvdModel. + + Args: + router_id: Subclass of AvdModel. + nexthop_fast_failover: nexthop_fast_failover + vrfs: Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`). + control_functions: + Routing control functions (RCF) used to filter and update routes from a peer or during + redistributions. + + Warning: + This configuration cannot be pushed with `eos_config_deploy_eapi`, because + of limitations in `arista.eos` and `ansible.netcommon` plugins. + The configuration can be pushed via + CloudVision with `eos_config_deploy_cvp` or `cv_deploy`. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class RouterIgmp(AvdModel): + """Subclass of AvdModel.""" + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "host_proxy_match_mroute": {"type": str}, "_custom_data": {"type": dict}} + name: str + """VRF name.""" + host_proxy_match_mroute: Literal["all", "iif"] | None + """ + Specify conditions for sending IGMP joins for host-proxy. + 'iif' will enable igmp host-proxy to work + in iif aware. + 'all' will enable igmp host-proxy to work in iif unaware mode (EOS default). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + host_proxy_match_mroute: Literal["all", "iif"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: VRF name. + host_proxy_match_mroute: + Specify conditions for sending IGMP joins for host-proxy. + 'iif' will enable igmp host-proxy to work + in iif aware. + 'all' will enable igmp host-proxy to work in iif unaware mode (EOS default). + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + _fields: ClassVar[dict] = { + "host_proxy_match_mroute": {"type": str}, + "ssm_aware": {"type": bool}, + "vrfs": {"type": Vrfs}, + "_custom_data": {"type": dict}, + } + host_proxy_match_mroute: Literal["all", "iif"] | None + """ + Specify conditions for sending IGMP joins for host-proxy. + 'iif' will enable igmp host-proxy to work + in iif aware. + 'all' will enable igmp host-proxy to work in iif unaware mode (EOS default). + """ + ssm_aware: bool | None + vrfs: Vrfs + """ + Configure IGMP in a VRF. + VRF 'default' is not supported in EOS, please see keys directly under + 'router_igmp'. + + Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + host_proxy_match_mroute: Literal["all", "iif"] | None | UndefinedType = Undefined, + ssm_aware: bool | None | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouterIgmp. + + + Subclass of AvdModel. + + Args: + host_proxy_match_mroute: + Specify conditions for sending IGMP joins for host-proxy. + 'iif' will enable igmp host-proxy to work + in iif aware. + 'all' will enable igmp host-proxy to work in iif unaware mode (EOS default). + ssm_aware: ssm_aware + vrfs: + Configure IGMP in a VRF. + VRF 'default' is not supported in EOS, please see keys directly under + 'router_igmp'. + + Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class RouterInternetExit(AvdModel): + """Subclass of AvdModel.""" + + class PoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + class ExitGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, name: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + ExitGroupsItem. + + + Subclass of AvdModel. + + Args: + name: name + _custom_data: _custom_data + + """ + + class ExitGroups(AvdList[ExitGroupsItem]): + """Subclass of AvdList with `ExitGroupsItem` items.""" + + ExitGroups._item_type = ExitGroupsItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "exit_groups": {"type": ExitGroups}, "_custom_data": {"type": dict}} + name: str + exit_groups: ExitGroups + """ + The exit groups that are configured under a policy are strictly ordered, meaning an exit group + appearing first has more priority than the exit group that follows it. + + Subclass of AvdList with + `ExitGroupsItem` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + exit_groups: ExitGroups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PoliciesItem. + + + Subclass of AvdModel. + + Args: + name: name + exit_groups: + The exit groups that are configured under a policy are strictly ordered, meaning an exit group + appearing first has more priority than the exit group that follows it. + + Subclass of AvdList with + `ExitGroupsItem` items. + _custom_data: _custom_data + + """ + + class Policies(AvdIndexedList[str, PoliciesItem]): + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Policies._item_type = PoliciesItem + + class ExitGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class LocalConnectionsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, name: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + LocalConnectionsItem. + + + Subclass of AvdModel. + + Args: + name: name + _custom_data: _custom_data + + """ + + class LocalConnections(AvdList[LocalConnectionsItem]): + """Subclass of AvdList with `LocalConnectionsItem` items.""" + + LocalConnections._item_type = LocalConnectionsItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "fib_default": {"type": bool}, + "local_connections": {"type": LocalConnections}, + "_custom_data": {"type": dict}, + } + name: str + fib_default: bool | None + """ + Fib default exit indicates that the flows that select this exit will follow the default route + available in the VRF of the flow. + """ + local_connections: LocalConnections + """ + Local connections refer to connections configured under the `router_service_insertion`. + The service- + insertion module reports the health of the connection and the exit will qualify for use only when it + is healthy. + + Subclass of AvdList with `LocalConnectionsItem` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + fib_default: bool | None | UndefinedType = Undefined, + local_connections: LocalConnections | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ExitGroupsItem. + + + Subclass of AvdModel. + + Args: + name: name + fib_default: + Fib default exit indicates that the flows that select this exit will follow the default route + available in the VRF of the flow. + local_connections: + Local connections refer to connections configured under the `router_service_insertion`. + The service- + insertion module reports the health of the connection and the exit will qualify for use only when it + is healthy. + + Subclass of AvdList with `LocalConnectionsItem` items. + _custom_data: _custom_data + + """ + + class ExitGroups(AvdIndexedList[str, ExitGroupsItem]): + """Subclass of AvdIndexedList with `ExitGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + ExitGroups._item_type = ExitGroupsItem + + _fields: ClassVar[dict] = {"policies": {"type": Policies}, "exit_groups": {"type": ExitGroups}, "_custom_data": {"type": dict}} + policies: Policies + """ + Internet-exit policy represent a policy which can be attached to a virtual topology profile. + Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`). + """ + exit_groups: ExitGroups + """ + Exit groups represent a group of exit options (connections). + Traffic flows are load balanced in a + round robin fashion across all the members (exits) of the exit-group. + + Subclass of AvdIndexedList + with `ExitGroupsItem` items. Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + policies: Policies | UndefinedType = Undefined, + exit_groups: ExitGroups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouterInternetExit. + + + Subclass of AvdModel. + + Args: + policies: + Internet-exit policy represent a policy which can be attached to a virtual topology profile. + Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`). + exit_groups: + Exit groups represent a group of exit options (connections). + Traffic flows are load balanced in a + round robin fashion across all the members (exits) of the exit-group. + + Subclass of AvdIndexedList + with `ExitGroupsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class RouterIsis(AvdModel): + """Subclass of AvdModel.""" + + class Timers(AvdModel): + """Subclass of AvdModel.""" + + class LocalConvergence(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"protected_prefixes": {"type": bool}, "delay": {"type": int, "default": 10000}, "_custom_data": {"type": dict}} + protected_prefixes: bool | None + delay: int + """ + Delay in milliseconds. + + Default value: `10000` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + protected_prefixes: bool | None | UndefinedType = Undefined, + delay: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LocalConvergence. + + + Subclass of AvdModel. + + Args: + protected_prefixes: protected_prefixes + delay: Delay in milliseconds. + _custom_data: _custom_data + + """ + + class Lsp(AvdModel): + """Subclass of AvdModel.""" + + class Generation(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "interval": {"type": int}, + "initial_wait_time": {"type": int}, + "wait_time": {"type": int}, + "_custom_data": {"type": dict}, + } + interval: int + """Maximum interval (in seconds) between generating two LSPs.""" + initial_wait_time: int | None + """Initial wait time (in milliseconds) before generating LSPs.""" + wait_time: int | None + """Wait time (in milliseconds) between generating the first and second LSPs.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | UndefinedType = Undefined, + initial_wait_time: int | None | UndefinedType = Undefined, + wait_time: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Generation. + + + Subclass of AvdModel. + + Args: + interval: Maximum interval (in seconds) between generating two LSPs. + initial_wait_time: Initial wait time (in milliseconds) before generating LSPs. + wait_time: Wait time (in milliseconds) between generating the first and second LSPs. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "generation": {"type": Generation}, + "out_delay": {"type": int}, + "refresh_interval": {"type": int}, + "min_remaining_lifetime": {"type": int}, + "_custom_data": {"type": dict}, + } + generation: Generation + """Subclass of AvdModel.""" + out_delay: int | None + """Transmit delay (in milliseconds) for link state packets.""" + refresh_interval: int | None + """Interval (in seconds) between two LSP refreshes.""" + min_remaining_lifetime: int | None + """Minimum remaining lifetime for LSPs (in seconds).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + generation: Generation | UndefinedType = Undefined, + out_delay: int | None | UndefinedType = Undefined, + refresh_interval: int | None | UndefinedType = Undefined, + min_remaining_lifetime: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Lsp. + + + Subclass of AvdModel. + + Args: + generation: Subclass of AvdModel. + out_delay: Transmit delay (in milliseconds) for link state packets. + refresh_interval: Interval (in seconds) between two LSP refreshes. + min_remaining_lifetime: Minimum remaining lifetime for LSPs (in seconds). + _custom_data: _custom_data + + """ + + class Csnp(AvdModel): + """Subclass of AvdModel.""" + + class Generation(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interval": {"type": int}, "p2p_disabled": {"type": bool}, "_custom_data": {"type": dict}} + interval: int | None + """Transmit frequency (in seconds) for CSN packets.""" + p2p_disabled: bool | None + """Disable periodic CSN packets for P2P links.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | None | UndefinedType = Undefined, + p2p_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Generation. + + + Subclass of AvdModel. + + Args: + interval: Transmit frequency (in seconds) for CSN packets. + p2p_disabled: Disable periodic CSN packets for P2P links. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"generation": {"type": Generation}, "_custom_data": {"type": dict}} + generation: Generation + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, generation: Generation | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Csnp. + + + Subclass of AvdModel. + + Args: + generation: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "local_convergence": {"type": LocalConvergence}, + "lsp": {"type": Lsp}, + "csnp": {"type": Csnp}, + "_custom_data": {"type": dict}, + } + local_convergence: LocalConvergence + """Subclass of AvdModel.""" + lsp: Lsp + """ + Link State Packet timers. + + Subclass of AvdModel. + """ + csnp: Csnp + """ + CSN Packet timers. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + local_convergence: LocalConvergence | UndefinedType = Undefined, + lsp: Lsp | UndefinedType = Undefined, + csnp: Csnp | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Timers. + + + Subclass of AvdModel. + + Args: + local_convergence: Subclass of AvdModel. + lsp: + Link State Packet timers. + + Subclass of AvdModel. + csnp: + CSN Packet timers. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class SetOverloadBit(AvdModel): + """Subclass of AvdModel.""" + + class OnStartup(AvdModel): + """Subclass of AvdModel.""" + + class WaitForBgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "timeout": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool | None + timeout: int | None + """Number of seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + timeout: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + WaitForBgp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + timeout: Number of seconds. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"delay": {"type": int}, "wait_for_bgp": {"type": WaitForBgp}, "_custom_data": {"type": dict}} + delay: int | None + """Number of seconds.""" + wait_for_bgp: WaitForBgp + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + delay: int | None | UndefinedType = Undefined, + wait_for_bgp: WaitForBgp | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + OnStartup. + + + Subclass of AvdModel. + + Args: + delay: Number of seconds. + wait_for_bgp: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "on_startup": {"type": OnStartup}, "_custom_data": {"type": dict}} + enabled: bool | None + on_startup: OnStartup + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + on_startup: OnStartup | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SetOverloadBit. + + + Subclass of AvdModel. + + Args: + enabled: enabled + on_startup: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Authentication(AvdModel): + """Subclass of AvdModel.""" + + class Both(AvdModel): + """Subclass of AvdModel.""" + + class KeyIdsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "algorithm": {"type": str}, + "key_type": {"type": str}, + "key": {"type": str}, + "rfc_5310": {"type": bool}, + "_custom_data": {"type": dict}, + } + id: int + """Configure authentication key-id.""" + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + key_type: Literal["0", "7", "8a"] + """Configure authentication key type.""" + key: str + """Password string.""" + rfc_5310: bool | None + """SHA digest computation according to rfc5310.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + key_type: Literal["0", "7", "8a"] | UndefinedType = Undefined, + key: str | UndefinedType = Undefined, + rfc_5310: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + KeyIdsItem. + + + Subclass of AvdModel. + + Args: + id: Configure authentication key-id. + algorithm: algorithm + key_type: Configure authentication key type. + key: Password string. + rfc_5310: SHA digest computation according to rfc5310. + _custom_data: _custom_data + + """ + + class KeyIds(AvdIndexedList[int, KeyIdsItem]): + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + KeyIds._item_type = KeyIdsItem + + class Sha(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"key_id": {"type": int}, "_custom_data": {"type": dict}} + key_id: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, key_id: int | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Sha. + + + Subclass of AvdModel. + + Args: + key_id: key_id + _custom_data: _custom_data + + """ + + class SharedSecret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "algorithm": {"type": str}, "_custom_data": {"type": dict}} + profile: str + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SharedSecret. + + + Subclass of AvdModel. + + Args: + profile: profile + algorithm: algorithm + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "key_type": {"type": str}, + "key": {"type": str}, + "key_ids": {"type": KeyIds}, + "mode": {"type": str}, + "sha": {"type": Sha}, + "shared_secret": {"type": SharedSecret}, + "rx_disabled": {"type": bool}, + "_custom_data": {"type": dict}, + } + key_type: Literal["0", "7", "8a"] | None + """Configure authentication key type.""" + key: str | None + """Password string. `key_type` is required for this setting.""" + key_ids: KeyIds + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + mode: Literal["md5", "sha", "text", "shared-secret"] | None + """Authentication mode.""" + sha: Sha + """ + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + """ + shared_secret: SharedSecret + """ + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + """ + rx_disabled: bool | None + """Disable authentication check on the receive side.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + key_type: Literal["0", "7", "8a"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + key_ids: KeyIds | UndefinedType = Undefined, + mode: Literal["md5", "sha", "text", "shared-secret"] | None | UndefinedType = Undefined, + sha: Sha | UndefinedType = Undefined, + shared_secret: SharedSecret | UndefinedType = Undefined, + rx_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Both. + + + Subclass of AvdModel. + + Args: + key_type: Configure authentication key type. + key: Password string. `key_type` is required for this setting. + key_ids: Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`). + mode: Authentication mode. + sha: + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + shared_secret: + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + rx_disabled: Disable authentication check on the receive side. + _custom_data: _custom_data + + """ + + class Level1(AvdModel): + """Subclass of AvdModel.""" + + class KeyIdsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "algorithm": {"type": str}, + "key_type": {"type": str}, + "key": {"type": str}, + "rfc_5310": {"type": bool}, + "_custom_data": {"type": dict}, + } + id: int + """Configure authentication key-id.""" + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + key_type: Literal["0", "7", "8a"] + """Configure authentication key type.""" + key: str + """Password string.""" + rfc_5310: bool | None + """SHA digest computation according to rfc5310.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + key_type: Literal["0", "7", "8a"] | UndefinedType = Undefined, + key: str | UndefinedType = Undefined, + rfc_5310: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + KeyIdsItem. + + + Subclass of AvdModel. + + Args: + id: Configure authentication key-id. + algorithm: algorithm + key_type: Configure authentication key type. + key: Password string. + rfc_5310: SHA digest computation according to rfc5310. + _custom_data: _custom_data + + """ + + class KeyIds(AvdIndexedList[int, KeyIdsItem]): + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + KeyIds._item_type = KeyIdsItem + + class Sha(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"key_id": {"type": int}, "_custom_data": {"type": dict}} + key_id: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, key_id: int | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Sha. + + + Subclass of AvdModel. + + Args: + key_id: key_id + _custom_data: _custom_data + + """ + + class SharedSecret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "algorithm": {"type": str}, "_custom_data": {"type": dict}} + profile: str + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SharedSecret. + + + Subclass of AvdModel. + + Args: + profile: profile + algorithm: algorithm + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "key_type": {"type": str}, + "key": {"type": str}, + "key_ids": {"type": KeyIds}, + "mode": {"type": str}, + "sha": {"type": Sha}, + "shared_secret": {"type": SharedSecret}, + "rx_disabled": {"type": bool}, + "_custom_data": {"type": dict}, + } + key_type: Literal["0", "7", "8a"] | None + """Configure authentication key type.""" + key: str | None + """Password string. `key_type` is required for this setting.""" + key_ids: KeyIds + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + mode: Literal["md5", "sha", "text", "shared-secret"] | None + """Authentication mode.""" + sha: Sha + """ + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + """ + shared_secret: SharedSecret + """ + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + """ + rx_disabled: bool | None + """Disable authentication check on the receive side.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + key_type: Literal["0", "7", "8a"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + key_ids: KeyIds | UndefinedType = Undefined, + mode: Literal["md5", "sha", "text", "shared-secret"] | None | UndefinedType = Undefined, + sha: Sha | UndefinedType = Undefined, + shared_secret: SharedSecret | UndefinedType = Undefined, + rx_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Level1. + + + Subclass of AvdModel. + + Args: + key_type: Configure authentication key type. + key: Password string. `key_type` is required for this setting. + key_ids: Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`). + mode: Authentication mode. + sha: + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + shared_secret: + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + rx_disabled: Disable authentication check on the receive side. + _custom_data: _custom_data + + """ + + class Level2(AvdModel): + """Subclass of AvdModel.""" + + class KeyIdsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "algorithm": {"type": str}, + "key_type": {"type": str}, + "key": {"type": str}, + "rfc_5310": {"type": bool}, + "_custom_data": {"type": dict}, + } + id: int + """Configure authentication key-id.""" + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + key_type: Literal["0", "7", "8a"] + """Configure authentication key type.""" + key: str + """Password string.""" + rfc_5310: bool | None + """SHA digest computation according to rfc5310.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + key_type: Literal["0", "7", "8a"] | UndefinedType = Undefined, + key: str | UndefinedType = Undefined, + rfc_5310: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + KeyIdsItem. + + + Subclass of AvdModel. + + Args: + id: Configure authentication key-id. + algorithm: algorithm + key_type: Configure authentication key type. + key: Password string. + rfc_5310: SHA digest computation according to rfc5310. + _custom_data: _custom_data + + """ + + class KeyIds(AvdIndexedList[int, KeyIdsItem]): + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + KeyIds._item_type = KeyIdsItem + + class Sha(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"key_id": {"type": int}, "_custom_data": {"type": dict}} + key_id: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, key_id: int | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Sha. + + + Subclass of AvdModel. + + Args: + key_id: key_id + _custom_data: _custom_data + + """ + + class SharedSecret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "algorithm": {"type": str}, "_custom_data": {"type": dict}} + profile: str + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SharedSecret. + + + Subclass of AvdModel. + + Args: + profile: profile + algorithm: algorithm + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "key_type": {"type": str}, + "key": {"type": str}, + "key_ids": {"type": KeyIds}, + "mode": {"type": str}, + "sha": {"type": Sha}, + "shared_secret": {"type": SharedSecret}, + "rx_disabled": {"type": bool}, + "_custom_data": {"type": dict}, + } + key_type: Literal["0", "7", "8a"] | None + """Configure authentication key type.""" + key: str | None + """Password string. `key_type` is required for this setting.""" + key_ids: KeyIds + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + mode: Literal["md5", "sha", "text", "shared-secret"] | None + """Authentication mode.""" + sha: Sha + """ + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + """ + shared_secret: SharedSecret + """ + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + """ + rx_disabled: bool | None + """Disable authentication check on the receive side.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + key_type: Literal["0", "7", "8a"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + key_ids: KeyIds | UndefinedType = Undefined, + mode: Literal["md5", "sha", "text", "shared-secret"] | None | UndefinedType = Undefined, + sha: Sha | UndefinedType = Undefined, + shared_secret: SharedSecret | UndefinedType = Undefined, + rx_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Level2. + + + Subclass of AvdModel. + + Args: + key_type: Configure authentication key type. + key: Password string. `key_type` is required for this setting. + key_ids: Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`). + mode: Authentication mode. + sha: + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + shared_secret: + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + rx_disabled: Disable authentication check on the receive side. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"both": {"type": Both}, "level_1": {"type": Level1}, "level_2": {"type": Level2}, "_custom_data": {"type": dict}} + both: Both + """ + Authentication settings for level-1 and level-2. 'both' takes precedence over 'level_1' and + 'level_2' settings. + + Subclass of AvdModel. + """ + level_1: Level1 + """ + Authentication settings for level-1. 'both' takes precedence over 'level_1' and 'level_2' settings. + Subclass of AvdModel. + """ + level_2: Level2 + """ + Authentication settings for level-2. 'both' takes precedence over 'level_1' and 'level_2' settings. + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + both: Both | UndefinedType = Undefined, + level_1: Level1 | UndefinedType = Undefined, + level_2: Level2 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Authentication. + + + Subclass of AvdModel. + + Args: + both: + Authentication settings for level-1 and level-2. 'both' takes precedence over 'level_1' and + 'level_2' settings. + + Subclass of AvdModel. + level_1: + Authentication settings for level-1. 'both' takes precedence over 'level_1' and 'level_2' settings. + Subclass of AvdModel. + level_2: + Authentication settings for level-2. 'both' takes precedence over 'level_1' and 'level_2' settings. + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Advertise(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"passive_only": {"type": bool}, "_custom_data": {"type": dict}} + passive_only: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, passive_only: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Advertise. + + + Subclass of AvdModel. + + Args: + passive_only: passive_only + _custom_data: _custom_data + + """ + + class RedistributeRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "source_protocol": {"type": str}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "ospf_route_type": {"type": str}, + "_custom_data": {"type": dict}, + } + source_protocol: Literal["bgp", "connected", "isis", "ospf", "ospfv3", "static"] + route_map: str | None + """Route-map name.""" + include_leaked: bool | None + ospf_route_type: Literal["external", "internal", "nssa-external"] | None + """ospf_route_type is required with source_protocols 'ospf' and 'ospfv3'.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source_protocol: Literal["bgp", "connected", "isis", "ospf", "ospfv3", "static"] | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + ospf_route_type: Literal["external", "internal", "nssa-external"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RedistributeRoutesItem. + + + Subclass of AvdModel. + + Args: + source_protocol: source_protocol + route_map: Route-map name. + include_leaked: include_leaked + ospf_route_type: ospf_route_type is required with source_protocols 'ospf' and 'ospfv3'. + _custom_data: _custom_data + + """ + + class RedistributeRoutes(AvdList[RedistributeRoutesItem]): + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + + RedistributeRoutes._item_type = RedistributeRoutesItem + + class AddressFamilyIpv4(AvdModel): + """Subclass of AvdModel.""" + + class FastRerouteTiLfa(AvdModel): + """Subclass of AvdModel.""" + + class Srlg(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enable": {"type": bool}, "strict": {"type": bool}, "_custom_data": {"type": dict}} + enable: bool | None + strict: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enable: bool | None | UndefinedType = Undefined, + strict: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Srlg. + + + Subclass of AvdModel. + + Args: + enable: enable + strict: strict + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"mode": {"type": str}, "level": {"type": str}, "srlg": {"type": Srlg}, "_custom_data": {"type": dict}} + mode: Literal["link-protection", "node-protection"] | None + level: Literal["level-1", "level-2"] | None + srlg: Srlg + """ + Shared Risk Link Group. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["link-protection", "node-protection"] | None | UndefinedType = Undefined, + level: Literal["level-1", "level-2"] | None | UndefinedType = Undefined, + srlg: Srlg | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FastRerouteTiLfa. + + + Subclass of AvdModel. + + Args: + mode: mode + level: level + srlg: + Shared Risk Link Group. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class TunnelSourceLabeledUnicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "rcf": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + rcf: str | None + """Route Control Function.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + rcf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TunnelSourceLabeledUnicast. + + + Subclass of AvdModel. + + Args: + enabled: enabled + rcf: Route Control Function. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "maximum_paths": {"type": int}, + "bfd_all_interfaces": {"type": bool}, + "fast_reroute_ti_lfa": {"type": FastRerouteTiLfa}, + "tunnel_source_labeled_unicast": {"type": TunnelSourceLabeledUnicast}, + "_custom_data": {"type": dict}, + } + enabled: bool + maximum_paths: int | None + bfd_all_interfaces: bool | None + """Enable BFD on all interfaces.""" + fast_reroute_ti_lfa: FastRerouteTiLfa + """Subclass of AvdModel.""" + tunnel_source_labeled_unicast: TunnelSourceLabeledUnicast + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + maximum_paths: int | None | UndefinedType = Undefined, + bfd_all_interfaces: bool | None | UndefinedType = Undefined, + fast_reroute_ti_lfa: FastRerouteTiLfa | UndefinedType = Undefined, + tunnel_source_labeled_unicast: TunnelSourceLabeledUnicast | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv4. + + + Subclass of AvdModel. + + Args: + enabled: enabled + maximum_paths: maximum_paths + bfd_all_interfaces: Enable BFD on all interfaces. + fast_reroute_ti_lfa: Subclass of AvdModel. + tunnel_source_labeled_unicast: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class AddressFamilyIpv6(AvdModel): + """Subclass of AvdModel.""" + + class FastRerouteTiLfa(AvdModel): + """Subclass of AvdModel.""" + + class Srlg(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enable": {"type": bool}, "strict": {"type": bool}, "_custom_data": {"type": dict}} + enable: bool | None + strict: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enable: bool | None | UndefinedType = Undefined, + strict: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Srlg. + + + Subclass of AvdModel. + + Args: + enable: enable + strict: strict + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"mode": {"type": str}, "level": {"type": str}, "srlg": {"type": Srlg}, "_custom_data": {"type": dict}} + mode: Literal["link-protection", "node-protection"] | None + level: Literal["level-1", "level-2"] | None + """Optional, default is to protect all levels.""" + srlg: Srlg + """ + Shared Risk Link Group. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["link-protection", "node-protection"] | None | UndefinedType = Undefined, + level: Literal["level-1", "level-2"] | None | UndefinedType = Undefined, + srlg: Srlg | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FastRerouteTiLfa. + + + Subclass of AvdModel. + + Args: + mode: mode + level: Optional, default is to protect all levels. + srlg: + Shared Risk Link Group. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "maximum_paths": {"type": int}, + "bfd_all_interfaces": {"type": bool}, + "fast_reroute_ti_lfa": {"type": FastRerouteTiLfa}, + "_custom_data": {"type": dict}, + } + enabled: bool + maximum_paths: int | None + bfd_all_interfaces: bool | None + """Enable BFD on all interfaces.""" + fast_reroute_ti_lfa: FastRerouteTiLfa + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + maximum_paths: int | None | UndefinedType = Undefined, + bfd_all_interfaces: bool | None | UndefinedType = Undefined, + fast_reroute_ti_lfa: FastRerouteTiLfa | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv6. + + + Subclass of AvdModel. + + Args: + enabled: enabled + maximum_paths: maximum_paths + bfd_all_interfaces: Enable BFD on all interfaces. + fast_reroute_ti_lfa: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class SegmentRoutingMpls(AvdModel): + """Subclass of AvdModel.""" + + class PrefixSegmentsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "index": {"type": int}, "_custom_data": {"type": dict}} + prefix: str | None + index: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix: str | None | UndefinedType = Undefined, + index: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PrefixSegmentsItem. + + + Subclass of AvdModel. + + Args: + prefix: prefix + index: index + _custom_data: _custom_data + + """ + + class PrefixSegments(AvdList[PrefixSegmentsItem]): + """Subclass of AvdList with `PrefixSegmentsItem` items.""" + + PrefixSegments._item_type = PrefixSegmentsItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "router_id": {"type": str}, + "prefix_segments": {"type": PrefixSegments}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + router_id: str | None + prefix_segments: PrefixSegments + """Subclass of AvdList with `PrefixSegmentsItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + router_id: str | None | UndefinedType = Undefined, + prefix_segments: PrefixSegments | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SegmentRoutingMpls. + + + Subclass of AvdModel. + + Args: + enabled: enabled + router_id: router_id + prefix_segments: Subclass of AvdList with `PrefixSegmentsItem` items. + _custom_data: _custom_data + + """ + + class SpfInterval(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "interval": {"type": int}, + "interval_unit": {"type": str}, + "wait_interval": {"type": int}, + "hold_interval": {"type": int}, + "_custom_data": {"type": dict}, + } + interval: int | None + """ + Maximum interval between two SPFs in seconds or milliseconds. + Range in seconds: <1-300> + Range in + milliseconds: <1-300000> + """ + interval_unit: Literal["seconds", "milliseconds"] | None + """If interval unit is not defined EOS takes `seconds` by default.""" + wait_interval: int | None + """Initial wait interval for SPF in milliseconds.""" + hold_interval: int | None + """Hold interval between the first and second SPF runs in milliseconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | None | UndefinedType = Undefined, + interval_unit: Literal["seconds", "milliseconds"] | None | UndefinedType = Undefined, + wait_interval: int | None | UndefinedType = Undefined, + hold_interval: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SpfInterval. + + + Subclass of AvdModel. + + Args: + interval: + Maximum interval between two SPFs in seconds or milliseconds. + Range in seconds: <1-300> + Range in + milliseconds: <1-300000> + interval_unit: If interval unit is not defined EOS takes `seconds` by default. + wait_interval: Initial wait interval for SPF in milliseconds. + hold_interval: Hold interval between the first and second SPF runs in milliseconds. + _custom_data: _custom_data + + """ + + class GracefulRestart(AvdModel): + """Subclass of AvdModel.""" + + class T2(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level_1_wait_time": {"type": int}, "level_2_wait_time": {"type": int}, "_custom_data": {"type": dict}} + level_1_wait_time: int | None + """Level-1 LSP database sync wait time in seconds.""" + level_2_wait_time: int | None + """Level-2 LSP database sync wait time in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level_1_wait_time: int | None | UndefinedType = Undefined, + level_2_wait_time: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + T2. + + + Subclass of AvdModel. + + Args: + level_1_wait_time: Level-1 LSP database sync wait time in seconds. + level_2_wait_time: Level-2 LSP database sync wait time in seconds. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "restart_hold_time": {"type": int}, "t2": {"type": T2}, "_custom_data": {"type": dict}} + enabled: bool | None + restart_hold_time: int | None + """Number of seconds.""" + t2: T2 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + restart_hold_time: int | None | UndefinedType = Undefined, + t2: T2 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GracefulRestart. + + + Subclass of AvdModel. + + Args: + enabled: enabled + restart_hold_time: Number of seconds. + t2: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "instance": {"type": str}, + "net": {"type": str}, + "router_id": {"type": str}, + "is_hostname": {"type": str}, + "is_type": {"type": str}, + "log_adjacency_changes": {"type": bool}, + "mpls_ldp_sync_default": {"type": bool}, + "timers": {"type": Timers}, + "set_overload_bit": {"type": SetOverloadBit}, + "authentication": {"type": Authentication}, + "advertise": {"type": Advertise}, + "redistribute_routes": {"type": RedistributeRoutes}, + "address_family_ipv4": {"type": AddressFamilyIpv4}, + "address_family_ipv6": {"type": AddressFamilyIpv6}, + "segment_routing_mpls": {"type": SegmentRoutingMpls}, + "spf_interval": {"type": SpfInterval}, + "graceful_restart": {"type": GracefulRestart}, + "eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + instance: str + """ISIS Instance Name.""" + net: str | None + """CLNS Address like "49.0001.0001.0000.0001.00".""" + router_id: str | None + """IPv4 Address.""" + is_hostname: str | None + """Hostname of Intermediate System.""" + is_type: Literal["level-1", "level-1-2", "level-2"] | None + log_adjacency_changes: bool | None + mpls_ldp_sync_default: bool | None + timers: Timers + """Subclass of AvdModel.""" + set_overload_bit: SetOverloadBit + """Subclass of AvdModel.""" + authentication: Authentication + """Subclass of AvdModel.""" + advertise: Advertise + """Subclass of AvdModel.""" + redistribute_routes: RedistributeRoutes + """Subclass of AvdList with `RedistributeRoutesItem` items.""" + address_family_ipv4: AddressFamilyIpv4 + """Subclass of AvdModel.""" + address_family_ipv6: AddressFamilyIpv6 + """Subclass of AvdModel.""" + segment_routing_mpls: SegmentRoutingMpls + """Subclass of AvdModel.""" + spf_interval: SpfInterval + """Subclass of AvdModel.""" + graceful_restart: GracefulRestart + """Subclass of AvdModel.""" + eos_cli: str | None + """Multiline EOS CLI rendered directly on the router isis in the final EOS configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + instance: str | UndefinedType = Undefined, + net: str | None | UndefinedType = Undefined, + router_id: str | None | UndefinedType = Undefined, + is_hostname: str | None | UndefinedType = Undefined, + is_type: Literal["level-1", "level-1-2", "level-2"] | None | UndefinedType = Undefined, + log_adjacency_changes: bool | None | UndefinedType = Undefined, + mpls_ldp_sync_default: bool | None | UndefinedType = Undefined, + timers: Timers | UndefinedType = Undefined, + set_overload_bit: SetOverloadBit | UndefinedType = Undefined, + authentication: Authentication | UndefinedType = Undefined, + advertise: Advertise | UndefinedType = Undefined, + redistribute_routes: RedistributeRoutes | UndefinedType = Undefined, + address_family_ipv4: AddressFamilyIpv4 | UndefinedType = Undefined, + address_family_ipv6: AddressFamilyIpv6 | UndefinedType = Undefined, + segment_routing_mpls: SegmentRoutingMpls | UndefinedType = Undefined, + spf_interval: SpfInterval | UndefinedType = Undefined, + graceful_restart: GracefulRestart | UndefinedType = Undefined, + eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouterIsis. + + + Subclass of AvdModel. + + Args: + instance: ISIS Instance Name. + net: CLNS Address like "49.0001.0001.0000.0001.00". + router_id: IPv4 Address. + is_hostname: Hostname of Intermediate System. + is_type: is_type + log_adjacency_changes: log_adjacency_changes + mpls_ldp_sync_default: mpls_ldp_sync_default + timers: Subclass of AvdModel. + set_overload_bit: Subclass of AvdModel. + authentication: Subclass of AvdModel. + advertise: Subclass of AvdModel. + redistribute_routes: Subclass of AvdList with `RedistributeRoutesItem` items. + address_family_ipv4: Subclass of AvdModel. + address_family_ipv6: Subclass of AvdModel. + segment_routing_mpls: Subclass of AvdModel. + spf_interval: Subclass of AvdModel. + graceful_restart: Subclass of AvdModel. + eos_cli: Multiline EOS CLI rendered directly on the router isis in the final EOS configuration. + _custom_data: _custom_data + + """ + + class RouterL2Vpn(AvdModel): + """Subclass of AvdModel.""" + + class ArpProxy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix_list": {"type": str}, "_custom_data": {"type": dict}} + prefix_list: str | None + """Prefix-list name. ARP Proxying is disabled for IPv4 addresses defined in the prefix-list.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, prefix_list: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + ArpProxy. + + + Subclass of AvdModel. + + Args: + prefix_list: Prefix-list name. ARP Proxying is disabled for IPv4 addresses defined in the prefix-list. + _custom_data: _custom_data + + """ + + class NdProxy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix_list": {"type": str}, "_custom_data": {"type": dict}} + prefix_list: str | None + """ + Prefix-list name. Neighbor Discovery Proxying is disabled for IPv6 addresses defined in the prefix- + list. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, prefix_list: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + NdProxy. + + + Subclass of AvdModel. + + Args: + prefix_list: + Prefix-list name. Neighbor Discovery Proxying is disabled for IPv6 addresses defined in the prefix- + list. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "arp_learning_bridged": {"type": bool}, + "arp_proxy": {"type": ArpProxy}, + "arp_selective_install": {"type": bool}, + "nd_learning_bridged": {"type": bool}, + "nd_proxy": {"type": NdProxy}, + "nd_rs_flooding_disabled": {"type": bool}, + "virtual_router_nd_ra_flooding_disabled": {"type": bool}, + "_custom_data": {"type": dict}, + } + arp_learning_bridged: bool | None + arp_proxy: ArpProxy + """Subclass of AvdModel.""" + arp_selective_install: bool | None + nd_learning_bridged: bool | None + nd_proxy: NdProxy + """Subclass of AvdModel.""" + nd_rs_flooding_disabled: bool | None + virtual_router_nd_ra_flooding_disabled: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + arp_learning_bridged: bool | None | UndefinedType = Undefined, + arp_proxy: ArpProxy | UndefinedType = Undefined, + arp_selective_install: bool | None | UndefinedType = Undefined, + nd_learning_bridged: bool | None | UndefinedType = Undefined, + nd_proxy: NdProxy | UndefinedType = Undefined, + nd_rs_flooding_disabled: bool | None | UndefinedType = Undefined, + virtual_router_nd_ra_flooding_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouterL2Vpn. + + + Subclass of AvdModel. + + Args: + arp_learning_bridged: arp_learning_bridged + arp_proxy: Subclass of AvdModel. + arp_selective_install: arp_selective_install + nd_learning_bridged: nd_learning_bridged + nd_proxy: Subclass of AvdModel. + nd_rs_flooding_disabled: nd_rs_flooding_disabled + virtual_router_nd_ra_flooding_disabled: virtual_router_nd_ra_flooding_disabled + _custom_data: _custom_data + + """ + + class RouterMsdp(AvdModel): + """Subclass of AvdModel.""" + + class GroupLimitsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"source_prefix": {"type": str}, "limit": {"type": int}, "_custom_data": {"type": dict}} + source_prefix: str + """Source address prefix.""" + limit: int + """Limit for SAs matching the source address prefix.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source_prefix: str | UndefinedType = Undefined, + limit: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GroupLimitsItem. + + + Subclass of AvdModel. + + Args: + source_prefix: Source address prefix. + limit: Limit for SAs matching the source address prefix. + _custom_data: _custom_data + + """ + + class GroupLimits(AvdIndexedList[str, GroupLimitsItem]): + """Subclass of AvdIndexedList with `GroupLimitsItem` items. Primary key is `source_prefix` (`str`).""" + + _primary_key: ClassVar[str] = "source_prefix" + + GroupLimits._item_type = GroupLimitsItem + + class PeersItem(AvdModel): + """Subclass of AvdModel.""" + + class DefaultPeer(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "prefix_list": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + prefix_list: str | None + """Prefix list to filter source of SA messages.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + prefix_list: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultPeer. + + + Subclass of AvdModel. + + Args: + enabled: enabled + prefix_list: Prefix list to filter source of SA messages. + _custom_data: _custom_data + + """ + + class MeshGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Mesh group name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, name: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + MeshGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Mesh group name. + _custom_data: _custom_data + + """ + + class MeshGroups(AvdIndexedList[str, MeshGroupsItem]): + """Subclass of AvdIndexedList with `MeshGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + MeshGroups._item_type = MeshGroupsItem + + class Keepalive(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"keepalive_timer": {"type": int}, "hold_timer": {"type": int}, "_custom_data": {"type": dict}} + keepalive_timer: int + hold_timer: int + """Must be greater than keepalive timer.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + keepalive_timer: int | UndefinedType = Undefined, + hold_timer: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Keepalive. + + + Subclass of AvdModel. + + Args: + keepalive_timer: keepalive_timer + hold_timer: Must be greater than keepalive timer. + _custom_data: _custom_data + + """ + + class SaFilter(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"in_list": {"type": str}, "out_list": {"type": str}, "_custom_data": {"type": dict}} + in_list: str | None + """ACL to filter inbound SA messages.""" + out_list: str | None + """ACL to filter outbound SA messages.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + in_list: str | None | UndefinedType = Undefined, + out_list: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SaFilter. + + + Subclass of AvdModel. + + Args: + in_list: ACL to filter inbound SA messages. + out_list: ACL to filter outbound SA messages. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ipv4_address": {"type": str}, + "default_peer": {"type": DefaultPeer}, + "local_interface": {"type": str}, + "description": {"type": str}, + "disabled": {"type": bool}, + "sa_limit": {"type": int}, + "mesh_groups": {"type": MeshGroups}, + "keepalive": {"type": Keepalive}, + "sa_filter": {"type": SaFilter}, + "_custom_data": {"type": dict}, + } + ipv4_address: str + """Peer IP Address.""" + default_peer: DefaultPeer + """Subclass of AvdModel.""" + local_interface: str | None + description: str | None + disabled: bool | None + """Disable the MSDP peer.""" + sa_limit: int | None + """Maximum number of SA messages allowed in cache.""" + mesh_groups: MeshGroups + """Subclass of AvdIndexedList with `MeshGroupsItem` items. Primary key is `name` (`str`).""" + keepalive: Keepalive + """Subclass of AvdModel.""" + sa_filter: SaFilter + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4_address: str | UndefinedType = Undefined, + default_peer: DefaultPeer | UndefinedType = Undefined, + local_interface: str | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + disabled: bool | None | UndefinedType = Undefined, + sa_limit: int | None | UndefinedType = Undefined, + mesh_groups: MeshGroups | UndefinedType = Undefined, + keepalive: Keepalive | UndefinedType = Undefined, + sa_filter: SaFilter | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeersItem. + + + Subclass of AvdModel. + + Args: + ipv4_address: Peer IP Address. + default_peer: Subclass of AvdModel. + local_interface: local_interface + description: description + disabled: Disable the MSDP peer. + sa_limit: Maximum number of SA messages allowed in cache. + mesh_groups: Subclass of AvdIndexedList with `MeshGroupsItem` items. Primary key is `name` (`str`). + keepalive: Subclass of AvdModel. + sa_filter: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Peers(AvdIndexedList[str, PeersItem]): + """Subclass of AvdIndexedList with `PeersItem` items. Primary key is `ipv4_address` (`str`).""" + + _primary_key: ClassVar[str] = "ipv4_address" + + Peers._item_type = PeersItem + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + class GroupLimitsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"source_prefix": {"type": str}, "limit": {"type": int}, "_custom_data": {"type": dict}} + source_prefix: str + """Source address prefix.""" + limit: int + """Limit for SAs matching the source address prefix.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source_prefix: str | UndefinedType = Undefined, + limit: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GroupLimitsItem. + + + Subclass of AvdModel. + + Args: + source_prefix: Source address prefix. + limit: Limit for SAs matching the source address prefix. + _custom_data: _custom_data + + """ + + class GroupLimits(AvdIndexedList[str, GroupLimitsItem]): + """Subclass of AvdIndexedList with `GroupLimitsItem` items. Primary key is `source_prefix` (`str`).""" + + _primary_key: ClassVar[str] = "source_prefix" + + GroupLimits._item_type = GroupLimitsItem + + class PeersItem(AvdModel): + """Subclass of AvdModel.""" + + class DefaultPeer(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "prefix_list": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + prefix_list: str | None + """Prefix list to filter source of SA messages.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + prefix_list: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultPeer. + + + Subclass of AvdModel. + + Args: + enabled: enabled + prefix_list: Prefix list to filter source of SA messages. + _custom_data: _custom_data + + """ + + class MeshGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Mesh group name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, name: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + MeshGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Mesh group name. + _custom_data: _custom_data + + """ + + class MeshGroups(AvdIndexedList[str, MeshGroupsItem]): + """Subclass of AvdIndexedList with `MeshGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + MeshGroups._item_type = MeshGroupsItem + + class Keepalive(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"keepalive_timer": {"type": int}, "hold_timer": {"type": int}, "_custom_data": {"type": dict}} + keepalive_timer: int + hold_timer: int + """Must be greater than keepalive timer.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + keepalive_timer: int | UndefinedType = Undefined, + hold_timer: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Keepalive. + + + Subclass of AvdModel. + + Args: + keepalive_timer: keepalive_timer + hold_timer: Must be greater than keepalive timer. + _custom_data: _custom_data + + """ + + class SaFilter(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"in_list": {"type": str}, "out_list": {"type": str}, "_custom_data": {"type": dict}} + in_list: str | None + """ACL to filter inbound SA messages.""" + out_list: str | None + """ACL to filter outbound SA messages.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + in_list: str | None | UndefinedType = Undefined, + out_list: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SaFilter. + + + Subclass of AvdModel. + + Args: + in_list: ACL to filter inbound SA messages. + out_list: ACL to filter outbound SA messages. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ipv4_address": {"type": str}, + "default_peer": {"type": DefaultPeer}, + "local_interface": {"type": str}, + "description": {"type": str}, + "disabled": {"type": bool}, + "sa_limit": {"type": int}, + "mesh_groups": {"type": MeshGroups}, + "keepalive": {"type": Keepalive}, + "sa_filter": {"type": SaFilter}, + "_custom_data": {"type": dict}, + } + ipv4_address: str + """Peer IP Address.""" + default_peer: DefaultPeer + """Subclass of AvdModel.""" + local_interface: str | None + description: str | None + disabled: bool | None + """Disable the MSDP peer.""" + sa_limit: int | None + """Maximum number of SA messages allowed in cache.""" + mesh_groups: MeshGroups + """Subclass of AvdIndexedList with `MeshGroupsItem` items. Primary key is `name` (`str`).""" + keepalive: Keepalive + """Subclass of AvdModel.""" + sa_filter: SaFilter + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4_address: str | UndefinedType = Undefined, + default_peer: DefaultPeer | UndefinedType = Undefined, + local_interface: str | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + disabled: bool | None | UndefinedType = Undefined, + sa_limit: int | None | UndefinedType = Undefined, + mesh_groups: MeshGroups | UndefinedType = Undefined, + keepalive: Keepalive | UndefinedType = Undefined, + sa_filter: SaFilter | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PeersItem. + + + Subclass of AvdModel. + + Args: + ipv4_address: Peer IP Address. + default_peer: Subclass of AvdModel. + local_interface: local_interface + description: description + disabled: Disable the MSDP peer. + sa_limit: Maximum number of SA messages allowed in cache. + mesh_groups: Subclass of AvdIndexedList with `MeshGroupsItem` items. Primary key is `name` (`str`). + keepalive: Subclass of AvdModel. + sa_filter: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Peers(AvdIndexedList[str, PeersItem]): + """Subclass of AvdIndexedList with `PeersItem` items. Primary key is `ipv4_address` (`str`).""" + + _primary_key: ClassVar[str] = "ipv4_address" + + Peers._item_type = PeersItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "originator_id_local_interface": {"type": str}, + "rejected_limit": {"type": int}, + "forward_register_packets": {"type": bool}, + "connection_retry_interval": {"type": int}, + "group_limits": {"type": GroupLimits}, + "peers": {"type": Peers}, + "_custom_data": {"type": dict}, + } + name: str + """VRF name.""" + originator_id_local_interface: str | None + """Interface to use for originator ID.""" + rejected_limit: int | None + """Maximum number of rejected SA messages allowed in cache.""" + forward_register_packets: bool | None + connection_retry_interval: int | None + group_limits: GroupLimits + """Subclass of AvdIndexedList with `GroupLimitsItem` items. Primary key is `source_prefix` (`str`).""" + peers: Peers + """Subclass of AvdIndexedList with `PeersItem` items. Primary key is `ipv4_address` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + originator_id_local_interface: str | None | UndefinedType = Undefined, + rejected_limit: int | None | UndefinedType = Undefined, + forward_register_packets: bool | None | UndefinedType = Undefined, + connection_retry_interval: int | None | UndefinedType = Undefined, + group_limits: GroupLimits | UndefinedType = Undefined, + peers: Peers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: VRF name. + originator_id_local_interface: Interface to use for originator ID. + rejected_limit: Maximum number of rejected SA messages allowed in cache. + forward_register_packets: forward_register_packets + connection_retry_interval: connection_retry_interval + group_limits: Subclass of AvdIndexedList with `GroupLimitsItem` items. Primary key is `source_prefix` (`str`). + peers: Subclass of AvdIndexedList with `PeersItem` items. Primary key is `ipv4_address` (`str`). + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + _fields: ClassVar[dict] = { + "originator_id_local_interface": {"type": str}, + "rejected_limit": {"type": int}, + "forward_register_packets": {"type": bool}, + "connection_retry_interval": {"type": int}, + "group_limits": {"type": GroupLimits}, + "peers": {"type": Peers}, + "vrfs": {"type": Vrfs}, + "_custom_data": {"type": dict}, + } + originator_id_local_interface: str | None + """Interface to use for originator ID.""" + rejected_limit: int | None + """Maximum number of rejected SA messages allowed in cache.""" + forward_register_packets: bool | None + connection_retry_interval: int | None + group_limits: GroupLimits + """Subclass of AvdIndexedList with `GroupLimitsItem` items. Primary key is `source_prefix` (`str`).""" + peers: Peers + """Subclass of AvdIndexedList with `PeersItem` items. Primary key is `ipv4_address` (`str`).""" + vrfs: Vrfs + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + originator_id_local_interface: str | None | UndefinedType = Undefined, + rejected_limit: int | None | UndefinedType = Undefined, + forward_register_packets: bool | None | UndefinedType = Undefined, + connection_retry_interval: int | None | UndefinedType = Undefined, + group_limits: GroupLimits | UndefinedType = Undefined, + peers: Peers | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouterMsdp. + + + Subclass of AvdModel. + + Args: + originator_id_local_interface: Interface to use for originator ID. + rejected_limit: Maximum number of rejected SA messages allowed in cache. + forward_register_packets: forward_register_packets + connection_retry_interval: connection_retry_interval + group_limits: Subclass of AvdIndexedList with `GroupLimitsItem` items. Primary key is `source_prefix` (`str`). + peers: Subclass of AvdIndexedList with `PeersItem` items. Primary key is `ipv4_address` (`str`). + vrfs: Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class RouterMulticast(AvdModel): + """Subclass of AvdModel.""" + + class Ipv4(AvdModel): + """Subclass of AvdModel.""" + + class Counters(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"rate_period_decay": {"type": int}, "_custom_data": {"type": dict}} + rate_period_decay: int | None + """Rate in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, rate_period_decay: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Counters. + + + Subclass of AvdModel. + + Args: + rate_period_decay: Rate in seconds. + _custom_data: _custom_data + + """ + + class Rpf(AvdModel): + """Subclass of AvdModel.""" + + class RoutesItem(AvdModel): + """Subclass of AvdModel.""" + + class DestinationsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"nexthop": {"type": str}, "distance": {"type": int}, "_custom_data": {"type": dict}} + nexthop: str + """Next-hop IP address or interface name.""" + distance: int | None + """Administrative distance for this route.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + nexthop: str | UndefinedType = Undefined, + distance: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DestinationsItem. + + + Subclass of AvdModel. + + Args: + nexthop: Next-hop IP address or interface name. + distance: Administrative distance for this route. + _custom_data: _custom_data + + """ + + class Destinations(AvdList[DestinationsItem]): + """Subclass of AvdList with `DestinationsItem` items.""" + + Destinations._item_type = DestinationsItem + + _fields: ClassVar[dict] = {"source_prefix": {"type": str}, "destinations": {"type": Destinations}, "_custom_data": {"type": dict}} + source_prefix: str + """Source address A.B.C.D or Source prefix A.B.C.D/E.""" + destinations: Destinations + """Subclass of AvdList with `DestinationsItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source_prefix: str | UndefinedType = Undefined, + destinations: Destinations | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RoutesItem. + + + Subclass of AvdModel. + + Args: + source_prefix: Source address A.B.C.D or Source prefix A.B.C.D/E. + destinations: Subclass of AvdList with `DestinationsItem` items. + _custom_data: _custom_data + + """ + + class Routes(AvdList[RoutesItem]): + """Subclass of AvdList with `RoutesItem` items.""" + + Routes._item_type = RoutesItem + + _fields: ClassVar[dict] = {"routes": {"type": Routes}, "_custom_data": {"type": dict}} + routes: Routes + """Subclass of AvdList with `RoutesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, routes: Routes | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Rpf. + + + Subclass of AvdModel. + + Args: + routes: Subclass of AvdList with `RoutesItem` items. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "activity_polling_interval": {"type": int}, + "counters": {"type": Counters}, + "routing": {"type": bool}, + "multipath": {"type": str}, + "software_forwarding": {"type": str}, + "rpf": {"type": Rpf}, + "_custom_data": {"type": dict}, + } + activity_polling_interval: int | None + """MFIB entry activity polling interval.""" + counters: Counters + """Subclass of AvdModel.""" + routing: bool | None + multipath: Literal["none", "deterministic", "deterministic color", "deterministic router-id"] | None + software_forwarding: Literal["kernel", "sfe"] | None + rpf: Rpf + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + activity_polling_interval: int | None | UndefinedType = Undefined, + counters: Counters | UndefinedType = Undefined, + routing: bool | None | UndefinedType = Undefined, + multipath: Literal["none", "deterministic", "deterministic color", "deterministic router-id"] | None | UndefinedType = Undefined, + software_forwarding: Literal["kernel", "sfe"] | None | UndefinedType = Undefined, + rpf: Rpf | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4. + + + Subclass of AvdModel. + + Args: + activity_polling_interval: MFIB entry activity polling interval. + counters: Subclass of AvdModel. + routing: routing + multipath: multipath + software_forwarding: software_forwarding + rpf: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Ipv6(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"activity_polling_interval": {"type": int}, "_custom_data": {"type": dict}} + activity_polling_interval: int | None + """MFIB entry activity polling interval.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, activity_polling_interval: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Ipv6. + + + Subclass of AvdModel. + + Args: + activity_polling_interval: MFIB entry activity polling interval. + _custom_data: _custom_data + + """ + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + class Ipv4(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"routing": {"type": bool}, "_custom_data": {"type": dict}} + routing: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, routing: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Ipv4. + + + Subclass of AvdModel. + + Args: + routing: routing + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"name": {"type": str}, "ipv4": {"type": Ipv4}, "_custom_data": {"type": dict}} + name: str + ipv4: Ipv4 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + ipv4: Ipv4 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: name + ipv4: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + _fields: ClassVar[dict] = {"ipv4": {"type": Ipv4}, "ipv6": {"type": Ipv6}, "vrfs": {"type": Vrfs}, "_custom_data": {"type": dict}} + ipv4: Ipv4 + """Subclass of AvdModel.""" + ipv6: Ipv6 + """Subclass of AvdModel.""" + vrfs: Vrfs + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4: Ipv4 | UndefinedType = Undefined, + ipv6: Ipv6 | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouterMulticast. + + + Subclass of AvdModel. + + Args: + ipv4: Subclass of AvdModel. + ipv6: Subclass of AvdModel. + vrfs: Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class RouterOspf(AvdModel): + """Subclass of AvdModel.""" + + class ProcessIdsItem(AvdModel): + """Subclass of AvdModel.""" + + class Distance(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"external": {"type": int}, "inter_area": {"type": int}, "intra_area": {"type": int}, "_custom_data": {"type": dict}} + external: int | None + inter_area: int | None + intra_area: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + external: int | None | UndefinedType = Undefined, + inter_area: int | None | UndefinedType = Undefined, + intra_area: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Distance. + + + Subclass of AvdModel. + + Args: + external: external + inter_area: inter_area + intra_area: intra_area + _custom_data: _custom_data + + """ + + class NetworkPrefixesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4_prefix": {"type": str}, "area": {"type": str}, "_custom_data": {"type": dict}} + ipv4_prefix: str + area: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4_prefix: str | UndefinedType = Undefined, + area: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NetworkPrefixesItem. + + + Subclass of AvdModel. + + Args: + ipv4_prefix: ipv4_prefix + area: area + _custom_data: _custom_data + + """ + + class NetworkPrefixes(AvdIndexedList[str, NetworkPrefixesItem]): + """Subclass of AvdIndexedList with `NetworkPrefixesItem` items. Primary key is `ipv4_prefix` (`str`).""" + + _primary_key: ClassVar[str] = "ipv4_prefix" + + NetworkPrefixes._item_type = NetworkPrefixesItem + + class NoPassiveInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + NoPassiveInterfaces._item_type = str + + class DistributeListIn(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"route_map": {"type": str}, "_custom_data": {"type": dict}} + route_map: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, route_map: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + DistributeListIn. + + + Subclass of AvdModel. + + Args: + route_map: route_map + _custom_data: _custom_data + + """ + + class Timers(AvdModel): + """Subclass of AvdModel.""" + + class Lsa(AvdModel): + """Subclass of AvdModel.""" + + class TxDelay(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"initial": {"type": int}, "min": {"type": int}, "max": {"type": int}, "_custom_data": {"type": dict}} + initial: int | None + """Delay to generate first occurrence of LSA in msecs.""" + min: int | None + """Min delay between originating the same LSA in msecs.""" + max: int | None + """1-600000 Maximum delay between originating the same LSA in msec.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + initial: int | None | UndefinedType = Undefined, + min: int | None | UndefinedType = Undefined, + max: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TxDelay. + + + Subclass of AvdModel. + + Args: + initial: Delay to generate first occurrence of LSA in msecs. + min: Min delay between originating the same LSA in msecs. + max: 1-600000 Maximum delay between originating the same LSA in msec. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"rx_min_interval": {"type": int}, "tx_delay": {"type": TxDelay}, "_custom_data": {"type": dict}} + rx_min_interval: int | None + """Min interval in msecs between accepting the same LSA.""" + tx_delay: TxDelay + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + rx_min_interval: int | None | UndefinedType = Undefined, + tx_delay: TxDelay | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Lsa. + + + Subclass of AvdModel. + + Args: + rx_min_interval: Min interval in msecs between accepting the same LSA. + tx_delay: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class SpfDelay(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"initial": {"type": int}, "min": {"type": int}, "max": {"type": int}, "_custom_data": {"type": dict}} + initial: int | None + """Initial SPF schedule delay in msecs.""" + min: int | None + """Min Hold time between two SPFs in msecs.""" + max: int | None + """Max wait time between two SPFs in msecs.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + initial: int | None | UndefinedType = Undefined, + min: int | None | UndefinedType = Undefined, + max: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SpfDelay. + + + Subclass of AvdModel. + + Args: + initial: Initial SPF schedule delay in msecs. + min: Min Hold time between two SPFs in msecs. + max: Max wait time between two SPFs in msecs. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"lsa": {"type": Lsa}, "spf_delay": {"type": SpfDelay}, "_custom_data": {"type": dict}} + lsa: Lsa + """Subclass of AvdModel.""" + spf_delay: SpfDelay + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + lsa: Lsa | UndefinedType = Undefined, + spf_delay: SpfDelay | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Timers. + + + Subclass of AvdModel. + + Args: + lsa: Subclass of AvdModel. + spf_delay: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class DefaultInformationOriginate(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"always": {"type": bool}, "metric": {"type": int}, "metric_type": {"type": int}, "_custom_data": {"type": dict}} + always: bool | None + metric: int | None + """Metric for default route.""" + metric_type: Literal[1, 2] | None + """OSPF metric type for default route.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + always: bool | None | UndefinedType = Undefined, + metric: int | None | UndefinedType = Undefined, + metric_type: Literal[1, 2] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultInformationOriginate. + + + Subclass of AvdModel. + + Args: + always: always + metric: Metric for default route. + metric_type: OSPF metric type for default route. + _custom_data: _custom_data + + """ + + class SummaryAddressesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "prefix": {"type": str}, + "tag": {"type": int}, + "attribute_map": {"type": str}, + "not_advertise": {"type": bool}, + "_custom_data": {"type": dict}, + } + prefix: str + """Summary Prefix Address.""" + tag: int | None + attribute_map: str | None + not_advertise: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefix: str | UndefinedType = Undefined, + tag: int | None | UndefinedType = Undefined, + attribute_map: str | None | UndefinedType = Undefined, + not_advertise: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SummaryAddressesItem. + + + Subclass of AvdModel. + + Args: + prefix: Summary Prefix Address. + tag: tag + attribute_map: attribute_map + not_advertise: not_advertise + _custom_data: _custom_data + + """ + + class SummaryAddresses(AvdIndexedList[str, SummaryAddressesItem]): + """Subclass of AvdIndexedList with `SummaryAddressesItem` items. Primary key is `prefix` (`str`).""" + + _primary_key: ClassVar[str] = "prefix" + + SummaryAddresses._item_type = SummaryAddressesItem + + class Redistribute(AvdModel): + """Subclass of AvdModel.""" + + class Static(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + """Route Map Name.""" + include_leaked: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Static. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: Route Map Name. + include_leaked: include_leaked + _custom_data: _custom_data + + """ + + class Connected(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + """Route Map Name.""" + include_leaked: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Connected. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: Route Map Name. + include_leaked: include_leaked + _custom_data: _custom_data + + """ + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "route_map": {"type": str}, + "include_leaked": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + route_map: str | None + """Route Map Name.""" + include_leaked: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + include_leaked: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: Route Map Name. + include_leaked: include_leaked + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"static": {"type": Static}, "connected": {"type": Connected}, "bgp": {"type": Bgp}, "_custom_data": {"type": dict}} + static: Static + """Subclass of AvdModel.""" + connected: Connected + """Subclass of AvdModel.""" + bgp: Bgp + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + static: Static | UndefinedType = Undefined, + connected: Connected | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Redistribute. + + + Subclass of AvdModel. + + Args: + static: Subclass of AvdModel. + connected: Subclass of AvdModel. + bgp: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class AreasItem(AvdModel): + """Subclass of AvdModel.""" + + class Filter(AvdModel): + """Subclass of AvdModel.""" + + class Networks(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Networks._item_type = str + + _fields: ClassVar[dict] = {"networks": {"type": Networks}, "prefix_list": {"type": str}, "_custom_data": {"type": dict}} + networks: Networks + """Subclass of AvdList with `str` items.""" + prefix_list: str | None + """Prefix-List Name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + networks: Networks | UndefinedType = Undefined, + prefix_list: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Filter. + + + Subclass of AvdModel. + + Args: + networks: Subclass of AvdList with `str` items. + prefix_list: Prefix-List Name. + _custom_data: _custom_data + + """ + + class DefaultInformationOriginate(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"metric": {"type": int}, "metric_type": {"type": int}, "_custom_data": {"type": dict}} + metric: int | None + """Metric for default route.""" + metric_type: Literal[1, 2] | None + """OSPF metric type for default route.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + metric: int | None | UndefinedType = Undefined, + metric_type: Literal[1, 2] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultInformationOriginate. + + + Subclass of AvdModel. + + Args: + metric: Metric for default route. + metric_type: OSPF metric type for default route. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "id": {"type": str}, + "filter": {"type": Filter}, + "type": {"type": str, "default": "normal"}, + "no_summary": {"type": bool}, + "nssa_only": {"type": bool}, + "default_information_originate": {"type": DefaultInformationOriginate}, + "_custom_data": {"type": dict}, + } + id: str + filter: Filter + """Subclass of AvdModel.""" + type: Literal["normal", "stub", "nssa"] + """Default value: `"normal"`""" + no_summary: bool | None + nssa_only: bool | None + default_information_originate: DefaultInformationOriginate + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: str | UndefinedType = Undefined, + filter: Filter | UndefinedType = Undefined, + type: Literal["normal", "stub", "nssa"] | UndefinedType = Undefined, + no_summary: bool | None | UndefinedType = Undefined, + nssa_only: bool | None | UndefinedType = Undefined, + default_information_originate: DefaultInformationOriginate | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AreasItem. + + + Subclass of AvdModel. + + Args: + id: id + filter: Subclass of AvdModel. + type: type + no_summary: no_summary + nssa_only: nssa_only + default_information_originate: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Areas(AvdIndexedList[str, AreasItem]): + """Subclass of AvdIndexedList with `AreasItem` items. Primary key is `id` (`str`).""" + + _primary_key: ClassVar[str] = "id" + + Areas._item_type = AreasItem + + class MaxMetric(AvdModel): + """Subclass of AvdModel.""" + + class RouterLsa(AvdModel): + """Subclass of AvdModel.""" + + class ExternalLsa(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"override_metric": {"type": int}, "_custom_data": {"type": dict}} + override_metric: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, override_metric: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + ExternalLsa. + + + Subclass of AvdModel. + + Args: + override_metric: override_metric + _custom_data: _custom_data + + """ + + class SummaryLsa(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"override_metric": {"type": int}, "_custom_data": {"type": dict}} + override_metric: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, override_metric: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + SummaryLsa. + + + Subclass of AvdModel. + + Args: + override_metric: override_metric + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "external_lsa": {"type": ExternalLsa}, + "include_stub": {"type": bool}, + "on_startup": {"type": str}, + "summary_lsa": {"type": SummaryLsa}, + "_custom_data": {"type": dict}, + } + external_lsa: ExternalLsa + """Subclass of AvdModel.""" + include_stub: bool | None + on_startup: str | None + """ + "wait-for-bgp" or Integer 5-86400. + Example: "wait-for-bgp" Or "222" + """ + summary_lsa: SummaryLsa + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + external_lsa: ExternalLsa | UndefinedType = Undefined, + include_stub: bool | None | UndefinedType = Undefined, + on_startup: str | None | UndefinedType = Undefined, + summary_lsa: SummaryLsa | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouterLsa. + + + Subclass of AvdModel. + + Args: + external_lsa: Subclass of AvdModel. + include_stub: include_stub + on_startup: + "wait-for-bgp" or Integer 5-86400. + Example: "wait-for-bgp" Or "222" + summary_lsa: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"router_lsa": {"type": RouterLsa}, "_custom_data": {"type": dict}} + router_lsa: RouterLsa + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, router_lsa: RouterLsa | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + MaxMetric. + + + Subclass of AvdModel. + + Args: + router_lsa: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class GracefulRestart(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "grace_period": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool + grace_period: int | None + """Specify maximum time in seconds to wait for graceful-restart to complete.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + grace_period: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GracefulRestart. + + + Subclass of AvdModel. + + Args: + enabled: enabled + grace_period: Specify maximum time in seconds to wait for graceful-restart to complete. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "vrf": {"type": str}, + "passive_interface_default": {"type": bool}, + "router_id": {"type": str}, + "distance": {"type": Distance}, + "log_adjacency_changes_detail": {"type": bool}, + "network_prefixes": {"type": NetworkPrefixes}, + "bfd_enable": {"type": bool}, + "bfd_adjacency_state_any": {"type": bool}, + "no_passive_interfaces": {"type": NoPassiveInterfaces}, + "distribute_list_in": {"type": DistributeListIn}, + "max_lsa": {"type": int}, + "timers": {"type": Timers}, + "default_information_originate": {"type": DefaultInformationOriginate}, + "summary_addresses": {"type": SummaryAddresses}, + "redistribute": {"type": Redistribute}, + "auto_cost_reference_bandwidth": {"type": int}, + "areas": {"type": Areas}, + "maximum_paths": {"type": int}, + "max_metric": {"type": MaxMetric}, + "graceful_restart": {"type": GracefulRestart}, + "graceful_restart_helper": {"type": bool}, + "mpls_ldp_sync_default": {"type": bool}, + "eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + id: int + """OSPF Process ID.""" + vrf: str | None + """VRF Name for OSPF Process.""" + passive_interface_default: bool | None + router_id: str | None + """IPv4 Address.""" + distance: Distance + """Subclass of AvdModel.""" + log_adjacency_changes_detail: bool | None + network_prefixes: NetworkPrefixes + """Subclass of AvdIndexedList with `NetworkPrefixesItem` items. Primary key is `ipv4_prefix` (`str`).""" + bfd_enable: bool | None + bfd_adjacency_state_any: bool | None + no_passive_interfaces: NoPassiveInterfaces + """Subclass of AvdList with `str` items.""" + distribute_list_in: DistributeListIn + """Subclass of AvdModel.""" + max_lsa: int | None + timers: Timers + """Subclass of AvdModel.""" + default_information_originate: DefaultInformationOriginate + """Subclass of AvdModel.""" + summary_addresses: SummaryAddresses + """Subclass of AvdIndexedList with `SummaryAddressesItem` items. Primary key is `prefix` (`str`).""" + redistribute: Redistribute + """Subclass of AvdModel.""" + auto_cost_reference_bandwidth: int | None + """Bandwidth in mbps.""" + areas: Areas + """Subclass of AvdIndexedList with `AreasItem` items. Primary key is `id` (`str`).""" + maximum_paths: int | None + max_metric: MaxMetric + """Subclass of AvdModel.""" + graceful_restart: GracefulRestart + """Subclass of AvdModel.""" + graceful_restart_helper: bool | None + mpls_ldp_sync_default: bool | None + eos_cli: str | None + """Multiline EOS CLI rendered directly on the Router OSPF process ID in the final EOS configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + passive_interface_default: bool | None | UndefinedType = Undefined, + router_id: str | None | UndefinedType = Undefined, + distance: Distance | UndefinedType = Undefined, + log_adjacency_changes_detail: bool | None | UndefinedType = Undefined, + network_prefixes: NetworkPrefixes | UndefinedType = Undefined, + bfd_enable: bool | None | UndefinedType = Undefined, + bfd_adjacency_state_any: bool | None | UndefinedType = Undefined, + no_passive_interfaces: NoPassiveInterfaces | UndefinedType = Undefined, + distribute_list_in: DistributeListIn | UndefinedType = Undefined, + max_lsa: int | None | UndefinedType = Undefined, + timers: Timers | UndefinedType = Undefined, + default_information_originate: DefaultInformationOriginate | UndefinedType = Undefined, + summary_addresses: SummaryAddresses | UndefinedType = Undefined, + redistribute: Redistribute | UndefinedType = Undefined, + auto_cost_reference_bandwidth: int | None | UndefinedType = Undefined, + areas: Areas | UndefinedType = Undefined, + maximum_paths: int | None | UndefinedType = Undefined, + max_metric: MaxMetric | UndefinedType = Undefined, + graceful_restart: GracefulRestart | UndefinedType = Undefined, + graceful_restart_helper: bool | None | UndefinedType = Undefined, + mpls_ldp_sync_default: bool | None | UndefinedType = Undefined, + eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ProcessIdsItem. + + + Subclass of AvdModel. + + Args: + id: OSPF Process ID. + vrf: VRF Name for OSPF Process. + passive_interface_default: passive_interface_default + router_id: IPv4 Address. + distance: Subclass of AvdModel. + log_adjacency_changes_detail: log_adjacency_changes_detail + network_prefixes: Subclass of AvdIndexedList with `NetworkPrefixesItem` items. Primary key is `ipv4_prefix` (`str`). + bfd_enable: bfd_enable + bfd_adjacency_state_any: bfd_adjacency_state_any + no_passive_interfaces: Subclass of AvdList with `str` items. + distribute_list_in: Subclass of AvdModel. + max_lsa: max_lsa + timers: Subclass of AvdModel. + default_information_originate: Subclass of AvdModel. + summary_addresses: Subclass of AvdIndexedList with `SummaryAddressesItem` items. Primary key is `prefix` (`str`). + redistribute: Subclass of AvdModel. + auto_cost_reference_bandwidth: Bandwidth in mbps. + areas: Subclass of AvdIndexedList with `AreasItem` items. Primary key is `id` (`str`). + maximum_paths: maximum_paths + max_metric: Subclass of AvdModel. + graceful_restart: Subclass of AvdModel. + graceful_restart_helper: graceful_restart_helper + mpls_ldp_sync_default: mpls_ldp_sync_default + eos_cli: Multiline EOS CLI rendered directly on the Router OSPF process ID in the final EOS configuration. + _custom_data: _custom_data + + """ + + class ProcessIds(AvdIndexedList[int, ProcessIdsItem]): + """Subclass of AvdIndexedList with `ProcessIdsItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + ProcessIds._item_type = ProcessIdsItem + + _fields: ClassVar[dict] = {"process_ids": {"type": ProcessIds}, "_custom_data": {"type": dict}} + process_ids: ProcessIds + """Subclass of AvdIndexedList with `ProcessIdsItem` items. Primary key is `id` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, process_ids: ProcessIds | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + RouterOspf. + + + Subclass of AvdModel. + + Args: + process_ids: Subclass of AvdIndexedList with `ProcessIdsItem` items. Primary key is `id` (`int`). + _custom_data: _custom_data + + """ + + class RouterPathSelection(AvdModel): + """Subclass of AvdModel.""" + + class PathGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class LocalInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Stun(AvdModel): + """Subclass of AvdModel.""" + + class ServerProfiles(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + ServerProfiles._item_type = str + + _fields: ClassVar[dict] = {"server_profiles": {"type": ServerProfiles}, "_custom_data": {"type": dict}} + server_profiles: ServerProfiles + """ + STUN server-profile names. + + Subclass of AvdList with `str` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, server_profiles: ServerProfiles | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Stun. + + + Subclass of AvdModel. + + Args: + server_profiles: + STUN server-profile names. + + Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"name": {"type": str}, "public_address": {"type": str}, "stun": {"type": Stun}, "_custom_data": {"type": dict}} + name: str + """Local interface name.""" + public_address: str | None + """Public IP assigned by NAT.""" + stun: Stun + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + public_address: str | None | UndefinedType = Undefined, + stun: Stun | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LocalInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: Local interface name. + public_address: Public IP assigned by NAT. + stun: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class LocalInterfaces(AvdIndexedList[str, LocalInterfacesItem]): + """Subclass of AvdIndexedList with `LocalInterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + LocalInterfaces._item_type = LocalInterfacesItem + + class LocalIpsItem(AvdModel): + """Subclass of AvdModel.""" + + class Stun(AvdModel): + """Subclass of AvdModel.""" + + class ServerProfiles(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + ServerProfiles._item_type = str + + _fields: ClassVar[dict] = {"server_profiles": {"type": ServerProfiles}, "_custom_data": {"type": dict}} + server_profiles: ServerProfiles + """ + STUN server-profile names. + + Subclass of AvdList with `str` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, server_profiles: ServerProfiles | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Stun. + + + Subclass of AvdModel. + + Args: + server_profiles: + STUN server-profile names. + + Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ip_address": {"type": str}, "public_address": {"type": str}, "stun": {"type": Stun}, "_custom_data": {"type": dict}} + ip_address: str + public_address: str | None + """Public IP assigned by NAT.""" + stun: Stun + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + public_address: str | None | UndefinedType = Undefined, + stun: Stun | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LocalIpsItem. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + public_address: Public IP assigned by NAT. + stun: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class LocalIps(AvdIndexedList[str, LocalIpsItem]): + """Subclass of AvdIndexedList with `LocalIpsItem` items. Primary key is `ip_address` (`str`).""" + + _primary_key: ClassVar[str] = "ip_address" + + LocalIps._item_type = LocalIpsItem + + class DynamicPeers(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "ip_local": {"type": bool}, "ipsec": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + """Enable `peer dynamic`.""" + ip_local: bool | None + """Prefer local IP address.""" + ipsec: bool | None + """IPsec configuration for dynamic peers.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + ip_local: bool | None | UndefinedType = Undefined, + ipsec: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DynamicPeers. + + + Subclass of AvdModel. + + Args: + enabled: Enable `peer dynamic`. + ip_local: Prefer local IP address. + ipsec: IPsec configuration for dynamic peers. + _custom_data: _custom_data + + """ + + class StaticPeersItem(AvdModel): + """Subclass of AvdModel.""" + + class Ipv4Addresses(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Ipv4Addresses._item_type = str + + _fields: ClassVar[dict] = { + "router_ip": {"type": str}, + "name": {"type": str}, + "ipv4_addresses": {"type": Ipv4Addresses}, + "_custom_data": {"type": dict}, + } + router_ip: str + """Peer router IP.""" + name: str | None + """Name of the site.""" + ipv4_addresses: Ipv4Addresses + """ + Static IPv4 addresses. + + Subclass of AvdList with `str` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + router_ip: str | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + ipv4_addresses: Ipv4Addresses | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StaticPeersItem. + + + Subclass of AvdModel. + + Args: + router_ip: Peer router IP. + name: Name of the site. + ipv4_addresses: + Static IPv4 addresses. + + Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class StaticPeers(AvdIndexedList[str, StaticPeersItem]): + """Subclass of AvdIndexedList with `StaticPeersItem` items. Primary key is `router_ip` (`str`).""" + + _primary_key: ClassVar[str] = "router_ip" + + StaticPeers._item_type = StaticPeersItem + + class Keepalive(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "auto": {"type": bool, "default": False}, + "interval": {"type": int}, + "failure_threshold": {"type": int}, + "_custom_data": {"type": dict}, + } + auto: bool + """ + Enable adaptive keepalive and feedback interval. + + Default value: `False` + """ + interval: int | None + """Interval in milliseconds.""" + failure_threshold: int | None + """Failure threshold in number of intervals. Required when `interval` is set.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + auto: bool | UndefinedType = Undefined, + interval: int | None | UndefinedType = Undefined, + failure_threshold: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Keepalive. + + + Subclass of AvdModel. + + Args: + auto: Enable adaptive keepalive and feedback interval. + interval: Interval in milliseconds. + failure_threshold: Failure threshold in number of intervals. Required when `interval` is set. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "id": {"type": int}, + "ipsec_profile": {"type": str}, + "flow_assignment": {"type": str}, + "local_interfaces": {"type": LocalInterfaces}, + "local_ips": {"type": LocalIps}, + "dynamic_peers": {"type": DynamicPeers}, + "static_peers": {"type": StaticPeers}, + "keepalive": {"type": Keepalive}, + "_custom_data": {"type": dict}, + } + name: str + """Path group name.""" + id: int | None + """Path group ID.""" + ipsec_profile: str | None + """IPSec profile for the path group.""" + flow_assignment: Literal["lan"] | None + """Flow assignment `lan` can not be configured in a path group with dynamic peers.""" + local_interfaces: LocalInterfaces + """Subclass of AvdIndexedList with `LocalInterfacesItem` items. Primary key is `name` (`str`).""" + local_ips: LocalIps + """Subclass of AvdIndexedList with `LocalIpsItem` items. Primary key is `ip_address` (`str`).""" + dynamic_peers: DynamicPeers + """ + Flow assignment `lan` can not be configured in a path group with dynamic peers. + + Subclass of + AvdModel. + """ + static_peers: StaticPeers + """Subclass of AvdIndexedList with `StaticPeersItem` items. Primary key is `router_ip` (`str`).""" + keepalive: Keepalive + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + id: int | None | UndefinedType = Undefined, + ipsec_profile: str | None | UndefinedType = Undefined, + flow_assignment: Literal["lan"] | None | UndefinedType = Undefined, + local_interfaces: LocalInterfaces | UndefinedType = Undefined, + local_ips: LocalIps | UndefinedType = Undefined, + dynamic_peers: DynamicPeers | UndefinedType = Undefined, + static_peers: StaticPeers | UndefinedType = Undefined, + keepalive: Keepalive | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PathGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Path group name. + id: Path group ID. + ipsec_profile: IPSec profile for the path group. + flow_assignment: Flow assignment `lan` can not be configured in a path group with dynamic peers. + local_interfaces: Subclass of AvdIndexedList with `LocalInterfacesItem` items. Primary key is `name` (`str`). + local_ips: Subclass of AvdIndexedList with `LocalIpsItem` items. Primary key is `ip_address` (`str`). + dynamic_peers: + Flow assignment `lan` can not be configured in a path group with dynamic peers. + + Subclass of + AvdModel. + static_peers: Subclass of AvdIndexedList with `StaticPeersItem` items. Primary key is `router_ip` (`str`). + keepalive: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PathGroups(AvdIndexedList[str, PathGroupsItem]): + """Subclass of AvdIndexedList with `PathGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PathGroups._item_type = PathGroupsItem + + class LoadBalancePoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + class PathGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "priority": {"type": int}, "_custom_data": {"type": dict}} + name: str + """Path-group name.""" + priority: int | None + """ + Priority for this path-group. + The EOS default value is 1. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PathGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Path-group name. + priority: + Priority for this path-group. + The EOS default value is 1. + _custom_data: _custom_data + + """ + + class PathGroups(AvdIndexedList[str, PathGroupsItem]): + """Subclass of AvdIndexedList with `PathGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PathGroups._item_type = PathGroupsItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "lowest_hop_count": {"type": bool}, + "jitter": {"type": int}, + "latency": {"type": int}, + "loss_rate": {"type": str}, + "path_groups": {"type": PathGroups}, + "_custom_data": {"type": dict}, + } + name: str + """Load-balance policy name.""" + lowest_hop_count: bool | None + """Prefer paths with lowest hop-count.""" + jitter: int | None + """Jitter requirement for this load balance policy in milliseconds.""" + latency: int | None + """One way delay requirement for this load balance policy in milliseconds.""" + loss_rate: str | None + """ + Loss Rate requirement in percentage for this load balance policy. + Value between 0.00 and 100.00. + """ + path_groups: PathGroups + """ + List of path-groups to use for this load balance policy. + + Subclass of AvdIndexedList with + `PathGroupsItem` items. Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + lowest_hop_count: bool | None | UndefinedType = Undefined, + jitter: int | None | UndefinedType = Undefined, + latency: int | None | UndefinedType = Undefined, + loss_rate: str | None | UndefinedType = Undefined, + path_groups: PathGroups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LoadBalancePoliciesItem. + + + Subclass of AvdModel. + + Args: + name: Load-balance policy name. + lowest_hop_count: Prefer paths with lowest hop-count. + jitter: Jitter requirement for this load balance policy in milliseconds. + latency: One way delay requirement for this load balance policy in milliseconds. + loss_rate: + Loss Rate requirement in percentage for this load balance policy. + Value between 0.00 and 100.00. + path_groups: + List of path-groups to use for this load balance policy. + + Subclass of AvdIndexedList with + `PathGroupsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class LoadBalancePolicies(AvdIndexedList[str, LoadBalancePoliciesItem]): + """Subclass of AvdIndexedList with `LoadBalancePoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + LoadBalancePolicies._item_type = LoadBalancePoliciesItem + + class PoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + class DefaultMatch(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"load_balance": {"type": str}, "_custom_data": {"type": dict}} + load_balance: str | None + """Name of the load-balance policy.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, load_balance: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + DefaultMatch. + + + Subclass of AvdModel. + + Args: + load_balance: Name of the load-balance policy. + _custom_data: _custom_data + + """ + + class RulesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "application_profile": {"type": str}, + "load_balance": {"type": str}, + "_custom_data": {"type": dict}, + } + id: int + """Rule ID.""" + application_profile: str + load_balance: str | None + """Name of the load-balance policy.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + application_profile: str | UndefinedType = Undefined, + load_balance: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RulesItem. + + + Subclass of AvdModel. + + Args: + id: Rule ID. + application_profile: application_profile + load_balance: Name of the load-balance policy. + _custom_data: _custom_data + + """ + + class Rules(AvdIndexedList[int, RulesItem]): + """Subclass of AvdIndexedList with `RulesItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + Rules._item_type = RulesItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "default_match": {"type": DefaultMatch}, "rules": {"type": Rules}, "_custom_data": {"type": dict}} + name: str + """DPS policy name.""" + default_match: DefaultMatch + """Subclass of AvdModel.""" + rules: Rules + """Subclass of AvdIndexedList with `RulesItem` items. Primary key is `id` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + default_match: DefaultMatch | UndefinedType = Undefined, + rules: Rules | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PoliciesItem. + + + Subclass of AvdModel. + + Args: + name: DPS policy name. + default_match: Subclass of AvdModel. + rules: Subclass of AvdIndexedList with `RulesItem` items. Primary key is `id` (`int`). + _custom_data: _custom_data + + """ + + class Policies(AvdIndexedList[str, PoliciesItem]): + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Policies._item_type = PoliciesItem + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "path_selection_policy": {"type": str}, "_custom_data": {"type": dict}} + name: str + """VRF name.""" + path_selection_policy: str | None + """DPS policy name to use for this VRF.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + path_selection_policy: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: VRF name. + path_selection_policy: DPS policy name to use for this VRF. + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + class TcpMssCeiling(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4_segment_size": {"type": str}, "direction": {"type": str, "default": "ingress"}, "_custom_data": {"type": dict}} + ipv4_segment_size: str | None + """ + Segment Size for IPv4. + Can be an integer in the range 64-65515 or "auto". + "auto" will enable auto- + discovery which clamps the TCP MSS value to the minimum of all the direct paths + and multi-hop path + MTU towards a remote VTEP (minus 40bytes to account for IP + TCP header). + """ + direction: Literal["ingress"] + """ + Enforce on packets through DPS tunnel for a specific direction. + Only 'ingress' direction is + supported. + + Default value: `"ingress"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4_segment_size: str | None | UndefinedType = Undefined, + direction: Literal["ingress"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TcpMssCeiling. + + + Subclass of AvdModel. + + Args: + ipv4_segment_size: + Segment Size for IPv4. + Can be an integer in the range 64-65515 or "auto". + "auto" will enable auto- + discovery which clamps the TCP MSS value to the minimum of all the direct paths + and multi-hop path + MTU towards a remote VTEP (minus 40bytes to account for IP + TCP header). + direction: + Enforce on packets through DPS tunnel for a specific direction. + Only 'ingress' direction is + supported. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "peer_dynamic_source": {"type": str}, + "path_groups": {"type": PathGroups}, + "load_balance_policies": {"type": LoadBalancePolicies}, + "policies": {"type": Policies}, + "vrfs": {"type": Vrfs}, + "tcp_mss_ceiling": {"type": TcpMssCeiling}, + "_custom_data": {"type": dict}, + } + peer_dynamic_source: Literal["stun"] | None + """Source of dynamic peer discovery.""" + path_groups: PathGroups + """Subclass of AvdIndexedList with `PathGroupsItem` items. Primary key is `name` (`str`).""" + load_balance_policies: LoadBalancePolicies + """Subclass of AvdIndexedList with `LoadBalancePoliciesItem` items. Primary key is `name` (`str`).""" + policies: Policies + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + vrfs: Vrfs + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + tcp_mss_ceiling: TcpMssCeiling + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + peer_dynamic_source: Literal["stun"] | None | UndefinedType = Undefined, + path_groups: PathGroups | UndefinedType = Undefined, + load_balance_policies: LoadBalancePolicies | UndefinedType = Undefined, + policies: Policies | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + tcp_mss_ceiling: TcpMssCeiling | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouterPathSelection. + + + Subclass of AvdModel. + + Args: + peer_dynamic_source: Source of dynamic peer discovery. + path_groups: Subclass of AvdIndexedList with `PathGroupsItem` items. Primary key is `name` (`str`). + load_balance_policies: Subclass of AvdIndexedList with `LoadBalancePoliciesItem` items. Primary key is `name` (`str`). + policies: Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`). + vrfs: Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`). + tcp_mss_ceiling: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class RouterPimSparseMode(AvdModel): + """Subclass of AvdModel.""" + + class Ipv4(AvdModel): + """Subclass of AvdModel.""" + + class RpAddressesItem(AvdModel): + """Subclass of AvdModel.""" + + class Groups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Groups._item_type = str + + class AccessLists(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AccessLists._item_type = str + + _fields: ClassVar[dict] = { + "address": {"type": str}, + "groups": {"type": Groups}, + "access_lists": {"type": AccessLists}, + "priority": {"type": int}, + "hashmask": {"type": int}, + "override": {"type": bool}, + "_custom_data": {"type": dict}, + } + address: str + """RP Address.""" + groups: Groups + """Subclass of AvdList with `str` items.""" + access_lists: AccessLists + """Subclass of AvdList with `str` items.""" + priority: int | None + hashmask: int | None + override: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + address: str | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + access_lists: AccessLists | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + hashmask: int | None | UndefinedType = Undefined, + override: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RpAddressesItem. + + + Subclass of AvdModel. + + Args: + address: RP Address. + groups: Subclass of AvdList with `str` items. + access_lists: Subclass of AvdList with `str` items. + priority: priority + hashmask: hashmask + override: override + _custom_data: _custom_data + + """ + + class RpAddresses(AvdList[RpAddressesItem]): + """Subclass of AvdList with `RpAddressesItem` items.""" + + RpAddresses._item_type = RpAddressesItem + + class AnycastRpsItem(AvdModel): + """Subclass of AvdModel.""" + + class OtherAnycastRpAddressesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"address": {"type": str}, "register_count": {"type": int}, "_custom_data": {"type": dict}} + address: str + """Other Anycast RP Address.""" + register_count: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + address: str | UndefinedType = Undefined, + register_count: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + OtherAnycastRpAddressesItem. + + + Subclass of AvdModel. + + Args: + address: Other Anycast RP Address. + register_count: register_count + _custom_data: _custom_data + + """ + + class OtherAnycastRpAddresses(AvdIndexedList[str, OtherAnycastRpAddressesItem]): + """ + Subclass of AvdIndexedList with `OtherAnycastRpAddressesItem` items. Primary key is `address` + (`str`). + """ + + _primary_key: ClassVar[str] = "address" + + OtherAnycastRpAddresses._item_type = OtherAnycastRpAddressesItem + + _fields: ClassVar[dict] = { + "address": {"type": str}, + "other_anycast_rp_addresses": {"type": OtherAnycastRpAddresses}, + "_custom_data": {"type": dict}, + } + address: str + """Anycast RP Address.""" + other_anycast_rp_addresses: OtherAnycastRpAddresses + """ + Subclass of AvdIndexedList with `OtherAnycastRpAddressesItem` items. Primary key is `address` + (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + address: str | UndefinedType = Undefined, + other_anycast_rp_addresses: OtherAnycastRpAddresses | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AnycastRpsItem. + + + Subclass of AvdModel. + + Args: + address: Anycast RP Address. + other_anycast_rp_addresses: + Subclass of AvdIndexedList with `OtherAnycastRpAddressesItem` items. Primary key is `address` + (`str`). + _custom_data: _custom_data + + """ + + class AnycastRps(AvdIndexedList[str, AnycastRpsItem]): + """Subclass of AvdIndexedList with `AnycastRpsItem` items. Primary key is `address` (`str`).""" + + _primary_key: ClassVar[str] = "address" + + AnycastRps._item_type = AnycastRpsItem + + _fields: ClassVar[dict] = { + "bfd": {"type": bool}, + "make_before_break": {"type": bool}, + "ssm_range": {"type": str}, + "rp_addresses": {"type": RpAddresses}, + "anycast_rps": {"type": AnycastRps}, + "_custom_data": {"type": dict}, + } + bfd: bool | None + """Enable/Disable BFD.""" + make_before_break: bool | None + """Enable/Disable Make-Before-Break.""" + ssm_range: str | None + """IPv4 Prefix associated with SSM.""" + rp_addresses: RpAddresses + """Subclass of AvdList with `RpAddressesItem` items.""" + anycast_rps: AnycastRps + """Subclass of AvdIndexedList with `AnycastRpsItem` items. Primary key is `address` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + bfd: bool | None | UndefinedType = Undefined, + make_before_break: bool | None | UndefinedType = Undefined, + ssm_range: str | None | UndefinedType = Undefined, + rp_addresses: RpAddresses | UndefinedType = Undefined, + anycast_rps: AnycastRps | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4. + + + Subclass of AvdModel. + + Args: + bfd: Enable/Disable BFD. + make_before_break: Enable/Disable Make-Before-Break. + ssm_range: IPv4 Prefix associated with SSM. + rp_addresses: Subclass of AvdList with `RpAddressesItem` items. + anycast_rps: Subclass of AvdIndexedList with `AnycastRpsItem` items. Primary key is `address` (`str`). + _custom_data: _custom_data + + """ + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + class Ipv4(AvdModel): + """Subclass of AvdModel.""" + + class RpAddressesItem(AvdModel): + """Subclass of AvdModel.""" + + class Groups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Groups._item_type = str + + class AccessLists(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AccessLists._item_type = str + + _fields: ClassVar[dict] = { + "address": {"type": str}, + "groups": {"type": Groups}, + "access_lists": {"type": AccessLists}, + "priority": {"type": int}, + "hashmask": {"type": int}, + "override": {"type": bool}, + "_custom_data": {"type": dict}, + } + address: str + """RP Address.""" + groups: Groups + """Subclass of AvdList with `str` items.""" + access_lists: AccessLists + """Subclass of AvdList with `str` items.""" + priority: int | None + hashmask: int | None + override: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + address: str | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + access_lists: AccessLists | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + hashmask: int | None | UndefinedType = Undefined, + override: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RpAddressesItem. + + + Subclass of AvdModel. + + Args: + address: RP Address. + groups: Subclass of AvdList with `str` items. + access_lists: Subclass of AvdList with `str` items. + priority: priority + hashmask: hashmask + override: override + _custom_data: _custom_data + + """ + + class RpAddresses(AvdList[RpAddressesItem]): + """Subclass of AvdList with `RpAddressesItem` items.""" + + RpAddresses._item_type = RpAddressesItem + + _fields: ClassVar[dict] = { + "bfd": {"type": bool}, + "make_before_break": {"type": bool}, + "rp_addresses": {"type": RpAddresses}, + "_custom_data": {"type": dict}, + } + bfd: bool | None + """Enable/Disable BFD.""" + make_before_break: bool | None + """Enable/Disable Make-Before-Break.""" + rp_addresses: RpAddresses + """Subclass of AvdList with `RpAddressesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + bfd: bool | None | UndefinedType = Undefined, + make_before_break: bool | None | UndefinedType = Undefined, + rp_addresses: RpAddresses | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4. + + + Subclass of AvdModel. + + Args: + bfd: Enable/Disable BFD. + make_before_break: Enable/Disable Make-Before-Break. + rp_addresses: Subclass of AvdList with `RpAddressesItem` items. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"name": {"type": str}, "ipv4": {"type": Ipv4}, "_custom_data": {"type": dict}} + name: str + """VRF Name.""" + ipv4: Ipv4 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + ipv4: Ipv4 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: VRF Name. + ipv4: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + _fields: ClassVar[dict] = {"ipv4": {"type": Ipv4}, "vrfs": {"type": Vrfs}, "_custom_data": {"type": dict}} + ipv4: Ipv4 + """Subclass of AvdModel.""" + vrfs: Vrfs + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4: Ipv4 | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouterPimSparseMode. + + + Subclass of AvdModel. + + Args: + ipv4: Subclass of AvdModel. + vrfs: Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class RouterSegmentSecurity(AvdModel): + """Subclass of AvdModel.""" + + class PoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + class SequenceNumbersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "sequence": {"type": int}, + "application": {"type": str}, + "action": {"type": str}, + "log": {"type": bool}, + "stateless": {"type": bool, "default": True}, + "next_hop": {"type": str}, + "_custom_data": {"type": dict}, + } + sequence: int + """Sequence ID.""" + application: str + """The name of the application.""" + action: Literal["forward", "drop", "redirect"] + """ + The action to take - note that platform support for the redirect action is limited. The "redirect" + action also requires the 'next_hop' to be configured. + """ + log: bool | None + """Enable logging - note that platform support is limited.""" + stateless: bool + """ + Take action, regardless of state. Should be set to 'true' for MSS-G. + + Default value: `True` + """ + next_hop: str | None + """When the action is 'redirect', this indicates the IPv4 next hop to redirect to.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sequence: int | UndefinedType = Undefined, + application: str | UndefinedType = Undefined, + action: Literal["forward", "drop", "redirect"] | UndefinedType = Undefined, + log: bool | None | UndefinedType = Undefined, + stateless: bool | UndefinedType = Undefined, + next_hop: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceNumbersItem. + + + Subclass of AvdModel. + + Args: + sequence: Sequence ID. + application: The name of the application. + action: + The action to take - note that platform support for the redirect action is limited. The "redirect" + action also requires the 'next_hop' to be configured. + log: Enable logging - note that platform support is limited. + stateless: Take action, regardless of state. Should be set to 'true' for MSS-G. + next_hop: When the action is 'redirect', this indicates the IPv4 next hop to redirect to. + _custom_data: _custom_data + + """ + + class SequenceNumbers(AvdIndexedList[int, SequenceNumbersItem]): + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + + _primary_key: ClassVar[str] = "sequence" + + SequenceNumbers._item_type = SequenceNumbersItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "sequence_numbers": {"type": SequenceNumbers}, "_custom_data": {"type": dict}} + name: str + """Policy name.""" + sequence_numbers: SequenceNumbers + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + sequence_numbers: SequenceNumbers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PoliciesItem. + + + Subclass of AvdModel. + + Args: + name: Policy name. + sequence_numbers: Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`). + _custom_data: _custom_data + + """ + + class Policies(AvdIndexedList[str, PoliciesItem]): + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Policies._item_type = PoliciesItem + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + class SegmentsItem(AvdModel): + """Subclass of AvdModel.""" + + class Definition(AvdModel): + """Subclass of AvdModel.""" + + class Interfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Interfaces._item_type = str + + class MatchListsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "address_family": {"type": str}, + "covered_prefix_list": {"type": str}, + "prefix": {"type": str}, + "_custom_data": {"type": dict}, + } + address_family: Literal["ipv4", "ipv6"] + """Indicate which address-family the match list belongs to e.g. ipv4 or ipv6.""" + covered_prefix_list: str | None + """ + The name of the prefix-list. You can have a maximum of one per address-family. Mutually exclusive to + the use of match_list. If both are configured prefix takes precedence. + """ + prefix: str | None + """ + The name of the match-list. You can have a maximum of one per address-family. Mutually exclusive to + the use of covered_prefix_list. If both are configured prefix takes precedence. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + address_family: Literal["ipv4", "ipv6"] | UndefinedType = Undefined, + covered_prefix_list: str | None | UndefinedType = Undefined, + prefix: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchListsItem. + + + Subclass of AvdModel. + + Args: + address_family: Indicate which address-family the match list belongs to e.g. ipv4 or ipv6. + covered_prefix_list: + The name of the prefix-list. You can have a maximum of one per address-family. Mutually exclusive to + the use of match_list. If both are configured prefix takes precedence. + prefix: + The name of the match-list. You can have a maximum of one per address-family. Mutually exclusive to + the use of covered_prefix_list. If both are configured prefix takes precedence. + _custom_data: _custom_data + + """ + + class MatchLists(AvdIndexedList[str, MatchListsItem]): + """Subclass of AvdIndexedList with `MatchListsItem` items. Primary key is `address_family` (`str`).""" + + _primary_key: ClassVar[str] = "address_family" + + MatchLists._item_type = MatchListsItem + + _fields: ClassVar[dict] = {"interfaces": {"type": Interfaces}, "match_lists": {"type": MatchLists}, "_custom_data": {"type": dict}} + interfaces: Interfaces + """ + The names of the source interface e.g. Port-Channel1 - note that platform support is limited. + Subclass of AvdList with `str` items. + """ + match_lists: MatchLists + """ + The set of lists that define the segment. These can be a mix of IPv4 and IPv6 prefix or match lists. + Subclass of AvdIndexedList with `MatchListsItem` items. Primary key is `address_family` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interfaces: Interfaces | UndefinedType = Undefined, + match_lists: MatchLists | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Definition. + + + Subclass of AvdModel. + + Args: + interfaces: + The names of the source interface e.g. Port-Channel1 - note that platform support is limited. + Subclass of AvdList with `str` items. + match_lists: + The set of lists that define the segment. These can be a mix of IPv4 and IPv6 prefix or match lists. + Subclass of AvdIndexedList with `MatchListsItem` items. Primary key is `address_family` (`str`). + _custom_data: _custom_data + + """ + + class PoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"field_from": {"type": str}, "policy": {"type": str}, "_custom_data": {"type": dict}} + _field_to_key_map: ClassVar[dict] = {"field_from": "from"} + _key_to_field_map: ClassVar[dict] = {"from": "field_from"} + field_from: str + """The name of the source segment or 'forwarding-segments' for all segments.""" + policy: str | None + """ + The name of the policy to apply. The built-in policies are 'policy-forward-all' and 'policy-drop- + all'. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + field_from: str | UndefinedType = Undefined, + policy: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PoliciesItem. + + + Subclass of AvdModel. + + Args: + field_from: The name of the source segment or 'forwarding-segments' for all segments. + policy: + The name of the policy to apply. The built-in policies are 'policy-forward-all' and 'policy-drop- + all'. + _custom_data: _custom_data + + """ + + class Policies(AvdIndexedList[str, PoliciesItem]): + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `field_from` (`str`).""" + + _primary_key: ClassVar[str] = "field_from" + + Policies._item_type = PoliciesItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "definition": {"type": Definition}, + "policies": {"type": Policies}, + "fallback_policy": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Segment name.""" + definition: Definition + """Subclass of AvdModel.""" + policies: Policies + """ + The policies controlling traffic into the segment. + + Subclass of AvdIndexedList with `PoliciesItem` + items. Primary key is `field_from` (`str`). + """ + fallback_policy: str | None + """ + Only supported on the R3 series platforms, this allows a per-segment default policy to be specified + by name. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + definition: Definition | UndefinedType = Undefined, + policies: Policies | UndefinedType = Undefined, + fallback_policy: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SegmentsItem. + + + Subclass of AvdModel. + + Args: + name: Segment name. + definition: Subclass of AvdModel. + policies: + The policies controlling traffic into the segment. + + Subclass of AvdIndexedList with `PoliciesItem` + items. Primary key is `field_from` (`str`). + fallback_policy: + Only supported on the R3 series platforms, this allows a per-segment default policy to be specified + by name. + _custom_data: _custom_data + + """ + + class Segments(AvdIndexedList[str, SegmentsItem]): + """Subclass of AvdIndexedList with `SegmentsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Segments._item_type = SegmentsItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "segments": {"type": Segments}, "_custom_data": {"type": dict}} + name: str + segments: Segments + """Subclass of AvdIndexedList with `SegmentsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + segments: Segments | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: name + segments: Subclass of AvdIndexedList with `SegmentsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "policies": {"type": Policies}, "vrfs": {"type": Vrfs}, "_custom_data": {"type": dict}} + enabled: bool | None + policies: Policies + """ + Customised application policies. + Using the Application Traffic Recognition L4 profiles, custom + policies can be defined. The built-in application 'app-match-all' can be used to match any packets. + Note that this is stateless, so both the source and destination flows need to be considered. + Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`). + """ + vrfs: Vrfs + """ + The name of the VRF that the segments and policies are defined in. + + Subclass of AvdIndexedList with + `VrfsItem` items. Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + policies: Policies | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouterSegmentSecurity. + + + Subclass of AvdModel. + + Args: + enabled: enabled + policies: + Customised application policies. + Using the Application Traffic Recognition L4 profiles, custom + policies can be defined. The built-in application 'app-match-all' can be used to match any packets. + Note that this is stateless, so both the source and destination flows need to be considered. + Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`). + vrfs: + The name of the VRF that the segments and policies are defined in. + + Subclass of AvdIndexedList with + `VrfsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class RouterServiceInsertion(AvdModel): + """Subclass of AvdModel.""" + + class ConnectionsItem(AvdModel): + """Subclass of AvdModel.""" + + class EthernetInterface(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "next_hop": {"type": str}, "_custom_data": {"type": dict}} + name: str + """e.g. Ethernet2 or Ethernet2/2.2""" + next_hop: str + """Next-hop IPv4 address (without mask).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + next_hop: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EthernetInterface. + + + Subclass of AvdModel. + + Args: + name: e.g. Ethernet2 or Ethernet2/2.2 + next_hop: Next-hop IPv4 address (without mask). + _custom_data: _custom_data + + """ + + class TunnelInterface(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"primary": {"type": str}, "secondary": {"type": str}, "_custom_data": {"type": dict}} + primary: str | None + """e.g. Tunnel2""" + secondary: str | None + """e.g. Tunnel3""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + primary: str | None | UndefinedType = Undefined, + secondary: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TunnelInterface. + + + Subclass of AvdModel. + + Args: + primary: e.g. Tunnel2 + secondary: e.g. Tunnel3 + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "ethernet_interface": {"type": EthernetInterface}, + "tunnel_interface": {"type": TunnelInterface}, + "monitor_connectivity_host": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Connection name.""" + ethernet_interface: EthernetInterface + """ + Outgoing physical interface or subinterface to use for the connection. + If both `ethernet_interface` + and `tunnel_interface` are configured, `ethernet_interface` will be used. + + Subclass of AvdModel. + """ + tunnel_interface: TunnelInterface + """ + Outgoing tunnel interface(s) to use for this connection. + If both `ethernet_interface` and + `tunnel_interface` are configured, `ethernet_interface` will be used. + + Subclass of AvdModel. + """ + monitor_connectivity_host: str | None + """ + Name of the host defined under `monitor_connectivity.hosts` used to derive the health of the + connection. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + ethernet_interface: EthernetInterface | UndefinedType = Undefined, + tunnel_interface: TunnelInterface | UndefinedType = Undefined, + monitor_connectivity_host: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ConnectionsItem. + + + Subclass of AvdModel. + + Args: + name: Connection name. + ethernet_interface: + Outgoing physical interface or subinterface to use for the connection. + If both `ethernet_interface` + and `tunnel_interface` are configured, `ethernet_interface` will be used. + + Subclass of AvdModel. + tunnel_interface: + Outgoing tunnel interface(s) to use for this connection. + If both `ethernet_interface` and + `tunnel_interface` are configured, `ethernet_interface` will be used. + + Subclass of AvdModel. + monitor_connectivity_host: + Name of the host defined under `monitor_connectivity.hosts` used to derive the health of the + connection. + _custom_data: _custom_data + + """ + + class Connections(AvdIndexedList[str, ConnectionsItem]): + """Subclass of AvdIndexedList with `ConnectionsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Connections._item_type = ConnectionsItem + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "connections": {"type": Connections}, "_custom_data": {"type": dict}} + enabled: bool | None + connections: Connections + """Subclass of AvdIndexedList with `ConnectionsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + connections: Connections | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouterServiceInsertion. + + + Subclass of AvdModel. + + Args: + enabled: enabled + connections: Subclass of AvdIndexedList with `ConnectionsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class RouterTrafficEngineering(AvdModel): + """Subclass of AvdModel.""" + + class RouterId(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4": {"type": str}, "ipv6": {"type": str}, "_custom_data": {"type": dict}} + ipv4: str | None + ipv6: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4: str | None | UndefinedType = Undefined, + ipv6: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouterId. + + + Subclass of AvdModel. + + Args: + ipv4: ipv4 + ipv6: ipv6 + _custom_data: _custom_data + + """ + + class SegmentRouting(AvdModel): + """Subclass of AvdModel.""" + + class PolicyEndpointsItem(AvdModel): + """Subclass of AvdModel.""" + + class ColorsItem(AvdModel): + """Subclass of AvdModel.""" + + class PathGroupItem(AvdModel): + """Subclass of AvdModel.""" + + class SegmentListItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "label_stack": {"type": str}, + "weight": {"type": int}, + "index": {"type": int}, + "_custom_data": {"type": dict}, + } + label_stack: str | None + """ + Label Stack as string. + Example: "100 2000 30" + """ + weight: int | None + index: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + label_stack: str | None | UndefinedType = Undefined, + weight: int | None | UndefinedType = Undefined, + index: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SegmentListItem. + + + Subclass of AvdModel. + + Args: + label_stack: + Label Stack as string. + Example: "100 2000 30" + weight: weight + index: index + _custom_data: _custom_data + + """ + + class SegmentList(AvdList[SegmentListItem]): + """Subclass of AvdList with `SegmentListItem` items.""" + + SegmentList._item_type = SegmentListItem + + _fields: ClassVar[dict] = { + "preference": {"type": int}, + "explicit_null": {"type": str}, + "segment_list": {"type": SegmentList}, + "_custom_data": {"type": dict}, + } + preference: int | None + explicit_null: Literal["ipv4", "ipv6", "ipv4 ipv6", "none"] | None + segment_list: SegmentList + """Subclass of AvdList with `SegmentListItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + preference: int | None | UndefinedType = Undefined, + explicit_null: Literal["ipv4", "ipv6", "ipv4 ipv6", "none"] | None | UndefinedType = Undefined, + segment_list: SegmentList | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PathGroupItem. + + + Subclass of AvdModel. + + Args: + preference: preference + explicit_null: explicit_null + segment_list: Subclass of AvdList with `SegmentListItem` items. + _custom_data: _custom_data + + """ + + class PathGroup(AvdList[PathGroupItem]): + """Subclass of AvdList with `PathGroupItem` items.""" + + PathGroup._item_type = PathGroupItem + + _fields: ClassVar[dict] = { + "value": {"type": int}, + "binding_sid": {"type": int}, + "description": {"type": str}, + "name": {"type": str}, + "sbfd_remote_discriminator": {"type": str}, + "path_group": {"type": PathGroup}, + "_custom_data": {"type": dict}, + } + value: int + binding_sid: int | None + description: str | None + name: str | None + sbfd_remote_discriminator: str | None + """IPv4 address or 32 bit integer.""" + path_group: PathGroup + """Subclass of AvdList with `PathGroupItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + value: int | UndefinedType = Undefined, + binding_sid: int | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + sbfd_remote_discriminator: str | None | UndefinedType = Undefined, + path_group: PathGroup | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ColorsItem. + + + Subclass of AvdModel. + + Args: + value: value + binding_sid: binding_sid + description: description + name: name + sbfd_remote_discriminator: IPv4 address or 32 bit integer. + path_group: Subclass of AvdList with `PathGroupItem` items. + _custom_data: _custom_data + + """ + + class Colors(AvdIndexedList[int, ColorsItem]): + """Subclass of AvdIndexedList with `ColorsItem` items. Primary key is `value` (`int`).""" + + _primary_key: ClassVar[str] = "value" + + Colors._item_type = ColorsItem + + _fields: ClassVar[dict] = {"address": {"type": str}, "colors": {"type": Colors}, "_custom_data": {"type": dict}} + address: str | None + """IPv4 or IPv6 address.""" + colors: Colors + """Subclass of AvdIndexedList with `ColorsItem` items. Primary key is `value` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + address: str | None | UndefinedType = Undefined, + colors: Colors | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PolicyEndpointsItem. + + + Subclass of AvdModel. + + Args: + address: IPv4 or IPv6 address. + colors: Subclass of AvdIndexedList with `ColorsItem` items. Primary key is `value` (`int`). + _custom_data: _custom_data + + """ + + class PolicyEndpoints(AvdList[PolicyEndpointsItem]): + """Subclass of AvdList with `PolicyEndpointsItem` items.""" + + PolicyEndpoints._item_type = PolicyEndpointsItem + + _fields: ClassVar[dict] = {"colored_tunnel_rib": {"type": bool}, "policy_endpoints": {"type": PolicyEndpoints}, "_custom_data": {"type": dict}} + colored_tunnel_rib: bool | None + policy_endpoints: PolicyEndpoints + """Subclass of AvdList with `PolicyEndpointsItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + colored_tunnel_rib: bool | None | UndefinedType = Undefined, + policy_endpoints: PolicyEndpoints | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SegmentRouting. + + + Subclass of AvdModel. + + Args: + colored_tunnel_rib: colored_tunnel_rib + policy_endpoints: Subclass of AvdList with `PolicyEndpointsItem` items. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "router_id": {"type": RouterId}, + "segment_routing": {"type": SegmentRouting}, + "_custom_data": {"type": dict}, + } + enabled: bool + router_id: RouterId + """Subclass of AvdModel.""" + segment_routing: SegmentRouting + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + router_id: RouterId | UndefinedType = Undefined, + segment_routing: SegmentRouting | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RouterTrafficEngineering. + + + Subclass of AvdModel. + + Args: + enabled: enabled + router_id: Subclass of AvdModel. + segment_routing: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class ServiceRoutingConfigurationBgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"no_equals_default": {"type": bool}, "_custom_data": {"type": dict}} + no_equals_default: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, no_equals_default: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + ServiceRoutingConfigurationBgp. + + + Subclass of AvdModel. + + Args: + no_equals_default: no_equals_default + _custom_data: _custom_data + + """ + + class ServiceUnsupportedTransceiver(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"license_name": {"type": str}, "license_key": {"type": str}, "_custom_data": {"type": dict}} + license_name: str | None + license_key: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + license_name: str | None | UndefinedType = Undefined, + license_key: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ServiceUnsupportedTransceiver. + + + Subclass of AvdModel. + + Args: + license_name: license_name + license_key: license_key + _custom_data: _custom_data + + """ + + class Sflow(AvdModel): + """Subclass of AvdModel.""" + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + class DestinationsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"destination": {"type": str}, "port": {"type": int}, "_custom_data": {"type": dict}} + destination: str + """Sflow Destination IP Address.""" + port: int | None + """Port Number""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + destination: str | UndefinedType = Undefined, + port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DestinationsItem. + + + Subclass of AvdModel. + + Args: + destination: Sflow Destination IP Address. + port: Port Number + _custom_data: _custom_data + + """ + + class Destinations(AvdIndexedList[str, DestinationsItem]): + """Subclass of AvdIndexedList with `DestinationsItem` items. Primary key is `destination` (`str`).""" + + _primary_key: ClassVar[str] = "destination" + + Destinations._item_type = DestinationsItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "destinations": {"type": Destinations}, + "source": {"type": str}, + "source_interface": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + destinations: Destinations + """Subclass of AvdIndexedList with `DestinationsItem` items. Primary key is `destination` (`str`).""" + source: str | None + """ + Source IP Address. + "source" and "source_interface" are mutually exclusive. If both are defined, + "source_interface" takes precedence. + """ + source_interface: str | None + """Source Interface.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + destinations: Destinations | UndefinedType = Undefined, + source: str | None | UndefinedType = Undefined, + source_interface: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: name + destinations: Subclass of AvdIndexedList with `DestinationsItem` items. Primary key is `destination` (`str`). + source: + Source IP Address. + "source" and "source_interface" are mutually exclusive. If both are defined, + "source_interface" takes precedence. + source_interface: Source Interface. + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + class DestinationsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"destination": {"type": str}, "port": {"type": int}, "_custom_data": {"type": dict}} + destination: str + """Sflow Destination IP Address.""" + port: int | None + """Port Number.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + destination: str | UndefinedType = Undefined, + port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DestinationsItem. + + + Subclass of AvdModel. + + Args: + destination: Sflow Destination IP Address. + port: Port Number. + _custom_data: _custom_data + + """ + + class Destinations(AvdIndexedList[str, DestinationsItem]): + """Subclass of AvdIndexedList with `DestinationsItem` items. Primary key is `destination` (`str`).""" + + _primary_key: ClassVar[str] = "destination" + + Destinations._item_type = DestinationsItem + + class ExtensionsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "enabled": {"type": bool}, "_custom_data": {"type": dict}} + name: str + """Extension Name.""" + enabled: bool + """Enable or Disable Extension.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ExtensionsItem. + + + Subclass of AvdModel. + + Args: + name: Extension Name. + enabled: Enable or Disable Extension. + _custom_data: _custom_data + + """ + + class Extensions(AvdIndexedList[str, ExtensionsItem]): + """Subclass of AvdIndexedList with `ExtensionsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Extensions._item_type = ExtensionsItem + + class Interface(AvdModel): + """Subclass of AvdModel.""" + + class Disable(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"default": {"type": bool}, "_custom_data": {"type": dict}} + default: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, default: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Disable. + + + Subclass of AvdModel. + + Args: + default: default + _custom_data: _custom_data + + """ + + class Egress(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enable_default": {"type": bool}, "unmodified": {"type": bool}, "_custom_data": {"type": dict}} + enable_default: bool | None + """Enable egress sFlow by default.""" + unmodified: bool | None + """ + Enable egress sFlow unmodified. + Platform dependent feature. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enable_default: bool | None | UndefinedType = Undefined, + unmodified: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Egress. + + + Subclass of AvdModel. + + Args: + enable_default: Enable egress sFlow by default. + unmodified: + Enable egress sFlow unmodified. + Platform dependent feature. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"disable": {"type": Disable}, "egress": {"type": Egress}, "_custom_data": {"type": dict}} + disable: Disable + """Subclass of AvdModel.""" + egress: Egress + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + disable: Disable | UndefinedType = Undefined, + egress: Egress | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Interface. + + + Subclass of AvdModel. + + Args: + disable: Subclass of AvdModel. + egress: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class HardwareAcceleration(AvdModel): + """Subclass of AvdModel.""" + + class ModulesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "enabled": {"type": bool, "default": True}, "_custom_data": {"type": dict}} + name: str + enabled: bool + """Default value: `True`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ModulesItem. + + + Subclass of AvdModel. + + Args: + name: name + enabled: enabled + _custom_data: _custom_data + + """ + + class Modules(AvdIndexedList[str, ModulesItem]): + """Subclass of AvdIndexedList with `ModulesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Modules._item_type = ModulesItem + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "sample": {"type": int}, "modules": {"type": Modules}, "_custom_data": {"type": dict}} + enabled: bool | None + sample: int | None + modules: Modules + """Subclass of AvdIndexedList with `ModulesItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + sample: int | None | UndefinedType = Undefined, + modules: Modules | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + HardwareAcceleration. + + + Subclass of AvdModel. + + Args: + enabled: enabled + sample: sample + modules: Subclass of AvdIndexedList with `ModulesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "sample": {"type": int}, + "sample_input_subinterface": {"type": bool}, + "sample_output_subinterface": {"type": bool}, + "dangerous": {"type": bool}, + "polling_interval": {"type": int}, + "vrfs": {"type": Vrfs}, + "destinations": {"type": Destinations}, + "source": {"type": str}, + "source_interface": {"type": str}, + "extensions": {"type": Extensions}, + "interface": {"type": Interface}, + "run": {"type": bool}, + "hardware_acceleration": {"type": HardwareAcceleration}, + "_custom_data": {"type": dict}, + } + sample: int | None + sample_input_subinterface: bool | None + sample_output_subinterface: bool | None + dangerous: bool | None + polling_interval: int | None + """Polling interval in seconds.""" + vrfs: Vrfs + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + destinations: Destinations + """Subclass of AvdIndexedList with `DestinationsItem` items. Primary key is `destination` (`str`).""" + source: str | None + """ + Source IP Address. + "source" and "source_interface" are mutually exclusive. If both are defined, + "source_interface" takes precedence. + """ + source_interface: str | None + """Source Interface.""" + extensions: Extensions + """Subclass of AvdIndexedList with `ExtensionsItem` items. Primary key is `name` (`str`).""" + interface: Interface + """Subclass of AvdModel.""" + run: bool | None + hardware_acceleration: HardwareAcceleration + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sample: int | None | UndefinedType = Undefined, + sample_input_subinterface: bool | None | UndefinedType = Undefined, + sample_output_subinterface: bool | None | UndefinedType = Undefined, + dangerous: bool | None | UndefinedType = Undefined, + polling_interval: int | None | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + destinations: Destinations | UndefinedType = Undefined, + source: str | None | UndefinedType = Undefined, + source_interface: str | None | UndefinedType = Undefined, + extensions: Extensions | UndefinedType = Undefined, + interface: Interface | UndefinedType = Undefined, + run: bool | None | UndefinedType = Undefined, + hardware_acceleration: HardwareAcceleration | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Sflow. + + + Subclass of AvdModel. + + Args: + sample: sample + sample_input_subinterface: sample_input_subinterface + sample_output_subinterface: sample_output_subinterface + dangerous: dangerous + polling_interval: Polling interval in seconds. + vrfs: Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`). + destinations: Subclass of AvdIndexedList with `DestinationsItem` items. Primary key is `destination` (`str`). + source: + Source IP Address. + "source" and "source_interface" are mutually exclusive. If both are defined, + "source_interface" takes precedence. + source_interface: Source Interface. + extensions: Subclass of AvdIndexedList with `ExtensionsItem` items. Primary key is `name` (`str`). + interface: Subclass of AvdModel. + run: run + hardware_acceleration: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class SnmpServer(AvdModel): + """Subclass of AvdModel.""" + + class EngineIds(AvdModel): + """Subclass of AvdModel.""" + + class RemotesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"id": {"type": str}, "address": {"type": str}, "udp_port": {"type": int}, "_custom_data": {"type": dict}} + id: str | None + """Remote engine ID in hexadecimal.""" + address: str | None + """Hostname or IP of remote engine.""" + udp_port: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: str | None | UndefinedType = Undefined, + address: str | None | UndefinedType = Undefined, + udp_port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemotesItem. + + + Subclass of AvdModel. + + Args: + id: Remote engine ID in hexadecimal. + address: Hostname or IP of remote engine. + udp_port: udp_port + _custom_data: _custom_data + + """ + + class Remotes(AvdList[RemotesItem]): + """Subclass of AvdList with `RemotesItem` items.""" + + Remotes._item_type = RemotesItem + + _fields: ClassVar[dict] = {"local": {"type": str}, "remotes": {"type": Remotes}, "_custom_data": {"type": dict}} + local: str | None + """Engine ID in hexadecimal.""" + remotes: Remotes + """Subclass of AvdList with `RemotesItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + local: str | None | UndefinedType = Undefined, + remotes: Remotes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EngineIds. + + + Subclass of AvdModel. + + Args: + local: Engine ID in hexadecimal. + remotes: Subclass of AvdList with `RemotesItem` items. + _custom_data: _custom_data + + """ + + class CommunitiesItem(AvdModel): + """Subclass of AvdModel.""" + + class AccessListIpv4(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + """IPv4 access list name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, name: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + AccessListIpv4. + + + Subclass of AvdModel. + + Args: + name: IPv4 access list name. + _custom_data: _custom_data + + """ + + class AccessListIpv6(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + """IPv6 access list name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, name: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + AccessListIpv6. + + + Subclass of AvdModel. + + Args: + name: IPv6 access list name. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "access": {"type": str}, + "access_list_ipv4": {"type": AccessListIpv4}, + "access_list_ipv6": {"type": AccessListIpv6}, + "view": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Community name.""" + access: Literal["ro", "rw"] | None + access_list_ipv4: AccessListIpv4 + """Subclass of AvdModel.""" + access_list_ipv6: AccessListIpv6 + """Subclass of AvdModel.""" + view: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + access: Literal["ro", "rw"] | None | UndefinedType = Undefined, + access_list_ipv4: AccessListIpv4 | UndefinedType = Undefined, + access_list_ipv6: AccessListIpv6 | UndefinedType = Undefined, + view: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CommunitiesItem. + + + Subclass of AvdModel. + + Args: + name: Community name. + access: access + access_list_ipv4: Subclass of AvdModel. + access_list_ipv6: Subclass of AvdModel. + view: view + _custom_data: _custom_data + + """ + + class Communities(AvdIndexedList[str, CommunitiesItem]): + """Subclass of AvdIndexedList with `CommunitiesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Communities._item_type = CommunitiesItem + + class Ipv4AclsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + """IPv4 access list name.""" + vrf: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4AclsItem. + + + Subclass of AvdModel. + + Args: + name: IPv4 access list name. + vrf: vrf + _custom_data: _custom_data + + """ + + class Ipv4Acls(AvdList[Ipv4AclsItem]): + """Subclass of AvdList with `Ipv4AclsItem` items.""" + + Ipv4Acls._item_type = Ipv4AclsItem + + class Ipv6AclsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + """IPv6 access list name.""" + vrf: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6AclsItem. + + + Subclass of AvdModel. + + Args: + name: IPv6 access list name. + vrf: vrf + _custom_data: _custom_data + + """ + + class Ipv6Acls(AvdList[Ipv6AclsItem]): + """Subclass of AvdList with `Ipv6AclsItem` items.""" + + Ipv6Acls._item_type = Ipv6AclsItem + + class LocalInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Interface name.""" + vrf: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LocalInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: Interface name. + vrf: vrf + _custom_data: _custom_data + + """ + + class LocalInterfaces(AvdIndexedList[str, LocalInterfacesItem]): + """Subclass of AvdIndexedList with `LocalInterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + LocalInterfaces._item_type = LocalInterfacesItem + + class ViewsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "mib_family_name": {"type": str}, "included": {"type": bool}, "_custom_data": {"type": dict}} + name: str | None + """SNMP view name.""" + mib_family_name: str | None + included: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + mib_family_name: str | None | UndefinedType = Undefined, + included: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ViewsItem. + + + Subclass of AvdModel. + + Args: + name: SNMP view name. + mib_family_name: mib_family_name + included: included + _custom_data: _custom_data + + """ + + class Views(AvdList[ViewsItem]): + """Subclass of AvdList with `ViewsItem` items.""" + + Views._item_type = ViewsItem + + class GroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "version": {"type": str}, + "authentication": {"type": str}, + "read": {"type": str}, + "write": {"type": str}, + "notify": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str | None + """Group name.""" + version: Literal["v1", "v2c", "v3"] | None + authentication: Literal["auth", "noauth", "priv"] | None + read: str | None + """Read view.""" + write: str | None + """Write view.""" + notify: str | None + """Notify view.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + version: Literal["v1", "v2c", "v3"] | None | UndefinedType = Undefined, + authentication: Literal["auth", "noauth", "priv"] | None | UndefinedType = Undefined, + read: str | None | UndefinedType = Undefined, + write: str | None | UndefinedType = Undefined, + notify: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GroupsItem. + + + Subclass of AvdModel. + + Args: + name: Group name. + version: version + authentication: authentication + read: Read view. + write: Write view. + notify: Notify view. + _custom_data: _custom_data + + """ + + class Groups(AvdList[GroupsItem]): + """Subclass of AvdList with `GroupsItem` items.""" + + Groups._item_type = GroupsItem + + class UsersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "group": {"type": str}, + "remote_address": {"type": str}, + "udp_port": {"type": int}, + "version": {"type": str}, + "localized": {"type": str}, + "auth": {"type": str}, + "auth_passphrase": {"type": str}, + "priv": {"type": str}, + "priv_passphrase": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str | None + """Username.""" + group: str | None + """Group name.""" + remote_address: str | None + """ + Hostname or ip of remote engine. + The remote_address and udp_port are used for remote users. + """ + udp_port: int | None + """udp_port will not be used if no remote_address is configured.""" + version: Literal["v1", "v2c", "v3"] | None + localized: str | None + """Engine ID in hexadecimal for localizing auth and/or priv.""" + auth: str | None + """Hash algorithm.""" + auth_passphrase: str | None + """Hashed authentication passphrase if localized is used else cleartext authentication passphrase.""" + priv: str | None + """Encryption algorithm.""" + priv_passphrase: str | None + """Hashed privacy passphrase if localized is used else cleartext privacy passphrase.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + group: str | None | UndefinedType = Undefined, + remote_address: str | None | UndefinedType = Undefined, + udp_port: int | None | UndefinedType = Undefined, + version: Literal["v1", "v2c", "v3"] | None | UndefinedType = Undefined, + localized: str | None | UndefinedType = Undefined, + auth: str | None | UndefinedType = Undefined, + auth_passphrase: str | None | UndefinedType = Undefined, + priv: str | None | UndefinedType = Undefined, + priv_passphrase: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + UsersItem. + + + Subclass of AvdModel. + + Args: + name: Username. + group: Group name. + remote_address: + Hostname or ip of remote engine. + The remote_address and udp_port are used for remote users. + udp_port: udp_port will not be used if no remote_address is configured. + version: version + localized: Engine ID in hexadecimal for localizing auth and/or priv. + auth: Hash algorithm. + auth_passphrase: Hashed authentication passphrase if localized is used else cleartext authentication passphrase. + priv: Encryption algorithm. + priv_passphrase: Hashed privacy passphrase if localized is used else cleartext privacy passphrase. + _custom_data: _custom_data + + """ + + class Users(AvdList[UsersItem]): + """Subclass of AvdList with `UsersItem` items.""" + + Users._item_type = UsersItem + + class HostsItem(AvdModel): + """Subclass of AvdModel.""" + + class UsersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"username": {"type": str}, "authentication_level": {"type": str}, "_custom_data": {"type": dict}} + username: str | None + authentication_level: Literal["auth", "noauth", "priv"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + username: str | None | UndefinedType = Undefined, + authentication_level: Literal["auth", "noauth", "priv"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + UsersItem. + + + Subclass of AvdModel. + + Args: + username: username + authentication_level: authentication_level + _custom_data: _custom_data + + """ + + class Users(AvdList[UsersItem]): + """Subclass of AvdList with `UsersItem` items.""" + + Users._item_type = UsersItem + + _fields: ClassVar[dict] = { + "host": {"type": str}, + "vrf": {"type": str}, + "version": {"type": str}, + "community": {"type": str}, + "users": {"type": Users}, + "_custom_data": {"type": dict}, + } + host: str | None + """Host IP address or name.""" + vrf: str | None + version: Literal["1", "2c", "3"] | None + community: str | None + """Community name.""" + users: Users + """Subclass of AvdList with `UsersItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + host: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + version: Literal["1", "2c", "3"] | None | UndefinedType = Undefined, + community: str | None | UndefinedType = Undefined, + users: Users | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + HostsItem. + + + Subclass of AvdModel. + + Args: + host: Host IP address or name. + vrf: vrf + version: version + community: Community name. + users: Subclass of AvdList with `UsersItem` items. + _custom_data: _custom_data + + """ + + class Hosts(AvdList[HostsItem]): + """Subclass of AvdList with `HostsItem` items.""" + + Hosts._item_type = HostsItem + + class Traps(AvdModel): + """Subclass of AvdModel.""" + + class SnmpTrapsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "enabled": {"type": bool, "default": True}, "_custom_data": {"type": dict}} + name: str | None + """ + Enable or disable specific snmp-traps and their sub_traps. + Examples: + - "bgp" + - "bgp established" + """ + enabled: bool + """Default value: `True`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SnmpTrapsItem. + + + Subclass of AvdModel. + + Args: + name: + Enable or disable specific snmp-traps and their sub_traps. + Examples: # fmt: skip + - "bgp" + - "bgp established" + enabled: enabled + _custom_data: _custom_data + + """ + + class SnmpTraps(AvdList[SnmpTrapsItem]): + """Subclass of AvdList with `SnmpTrapsItem` items.""" + + SnmpTraps._item_type = SnmpTrapsItem + + _fields: ClassVar[dict] = {"enable": {"type": bool, "default": False}, "snmp_traps": {"type": SnmpTraps}, "_custom_data": {"type": dict}} + enable: bool + """ + Enable or disable all snmp-traps. + + Default value: `False` + """ + snmp_traps: SnmpTraps + """Subclass of AvdList with `SnmpTrapsItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enable: bool | UndefinedType = Undefined, + snmp_traps: SnmpTraps | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Traps. + + + Subclass of AvdModel. + + Args: + enable: Enable or disable all snmp-traps. + snmp_traps: Subclass of AvdList with `SnmpTrapsItem` items. + _custom_data: _custom_data + + """ + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "enable": {"type": bool}, "_custom_data": {"type": dict}} + name: str + """VRF name.""" + enable: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + enable: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: VRF name. + enable: enable + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + _fields: ClassVar[dict] = { + "engine_ids": {"type": EngineIds}, + "contact": {"type": str}, + "location": {"type": str}, + "communities": {"type": Communities}, + "ipv4_acls": {"type": Ipv4Acls}, + "ipv6_acls": {"type": Ipv6Acls}, + "local_interfaces": {"type": LocalInterfaces}, + "views": {"type": Views}, + "groups": {"type": Groups}, + "users": {"type": Users}, + "hosts": {"type": Hosts}, + "traps": {"type": Traps}, + "vrfs": {"type": Vrfs}, + "ifmib_ifspeed_shape_rate": {"type": bool}, + "_custom_data": {"type": dict}, + } + engine_ids: EngineIds + """Subclass of AvdModel.""" + contact: str | None + """SNMP contact.""" + location: str | None + """SNMP location.""" + communities: Communities + """Subclass of AvdIndexedList with `CommunitiesItem` items. Primary key is `name` (`str`).""" + ipv4_acls: Ipv4Acls + """Subclass of AvdList with `Ipv4AclsItem` items.""" + ipv6_acls: Ipv6Acls + """Subclass of AvdList with `Ipv6AclsItem` items.""" + local_interfaces: LocalInterfaces + """Subclass of AvdIndexedList with `LocalInterfacesItem` items. Primary key is `name` (`str`).""" + views: Views + """Subclass of AvdList with `ViewsItem` items.""" + groups: Groups + """Subclass of AvdList with `GroupsItem` items.""" + users: Users + """Subclass of AvdList with `UsersItem` items.""" + hosts: Hosts + """Subclass of AvdList with `HostsItem` items.""" + traps: Traps + """Subclass of AvdModel.""" + vrfs: Vrfs + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + ifmib_ifspeed_shape_rate: bool | None + """SNMP ifspeed reflecting shaping rate.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + engine_ids: EngineIds | UndefinedType = Undefined, + contact: str | None | UndefinedType = Undefined, + location: str | None | UndefinedType = Undefined, + communities: Communities | UndefinedType = Undefined, + ipv4_acls: Ipv4Acls | UndefinedType = Undefined, + ipv6_acls: Ipv6Acls | UndefinedType = Undefined, + local_interfaces: LocalInterfaces | UndefinedType = Undefined, + views: Views | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + users: Users | UndefinedType = Undefined, + hosts: Hosts | UndefinedType = Undefined, + traps: Traps | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + ifmib_ifspeed_shape_rate: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SnmpServer. + + + Subclass of AvdModel. + + Args: + engine_ids: Subclass of AvdModel. + contact: SNMP contact. + location: SNMP location. + communities: Subclass of AvdIndexedList with `CommunitiesItem` items. Primary key is `name` (`str`). + ipv4_acls: Subclass of AvdList with `Ipv4AclsItem` items. + ipv6_acls: Subclass of AvdList with `Ipv6AclsItem` items. + local_interfaces: Subclass of AvdIndexedList with `LocalInterfacesItem` items. Primary key is `name` (`str`). + views: Subclass of AvdList with `ViewsItem` items. + groups: Subclass of AvdList with `GroupsItem` items. + users: Subclass of AvdList with `UsersItem` items. + hosts: Subclass of AvdList with `HostsItem` items. + traps: Subclass of AvdModel. + vrfs: Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`). + ifmib_ifspeed_shape_rate: SNMP ifspeed reflecting shaping rate. + _custom_data: _custom_data + + """ + + class SpanningTree(AvdModel): + """Subclass of AvdModel.""" + + class EdgePort(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"bpdufilter_default": {"type": bool}, "bpduguard_default": {"type": bool}, "_custom_data": {"type": dict}} + bpdufilter_default: bool | None + bpduguard_default: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + bpdufilter_default: bool | None | UndefinedType = Undefined, + bpduguard_default: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EdgePort. + + + Subclass of AvdModel. + + Args: + bpdufilter_default: bpdufilter_default + bpduguard_default: bpduguard_default + _custom_data: _custom_data + + """ + + class BpduguardRateLimit(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"default": {"type": bool}, "count": {"type": int}, "_custom_data": {"type": dict}} + default: bool | None + count: int | None + """Maximum number of BPDUs per timer interval.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + default: bool | None | UndefinedType = Undefined, + count: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BpduguardRateLimit. + + + Subclass of AvdModel. + + Args: + default: default + count: Maximum number of BPDUs per timer interval. + _custom_data: _custom_data + + """ + + class Mst(AvdModel): + """Subclass of AvdModel.""" + + class Configuration(AvdModel): + """Subclass of AvdModel.""" + + class InstancesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"id": {"type": int}, "vlans": {"type": str}, "_custom_data": {"type": dict}} + id: int + """Instance ID.""" + vlans: str | None + """ + "< vlan_id >, < vlan_id >-< vlan_id >" + Example: 15,16,17,18 + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + vlans: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + InstancesItem. + + + Subclass of AvdModel. + + Args: + id: Instance ID. + vlans: + "< vlan_id >, < vlan_id >-< vlan_id >" + Example: 15,16,17,18 + _custom_data: _custom_data + + """ + + class Instances(AvdIndexedList[int, InstancesItem]): + """Subclass of AvdIndexedList with `InstancesItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + Instances._item_type = InstancesItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "revision": {"type": int}, "instances": {"type": Instances}, "_custom_data": {"type": dict}} + name: str | None + revision: int | None + """0-65535.""" + instances: Instances + """Subclass of AvdIndexedList with `InstancesItem` items. Primary key is `id` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + revision: int | None | UndefinedType = Undefined, + instances: Instances | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Configuration. + + + Subclass of AvdModel. + + Args: + name: name + revision: 0-65535. + instances: Subclass of AvdIndexedList with `InstancesItem` items. Primary key is `id` (`int`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"pvst_border": {"type": bool}, "configuration": {"type": Configuration}, "_custom_data": {"type": dict}} + pvst_border: bool | None + configuration: Configuration + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + pvst_border: bool | None | UndefinedType = Undefined, + configuration: Configuration | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Mst. + + + Subclass of AvdModel. + + Args: + pvst_border: pvst_border + configuration: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MstInstancesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"id": {"type": str}, "priority": {"type": int}, "_custom_data": {"type": dict}} + id: str + """Instance ID.""" + priority: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: str | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MstInstancesItem. + + + Subclass of AvdModel. + + Args: + id: Instance ID. + priority: priority + _custom_data: _custom_data + + """ + + class MstInstances(AvdIndexedList[str, MstInstancesItem]): + """Subclass of AvdIndexedList with `MstInstancesItem` items. Primary key is `id` (`str`).""" + + _primary_key: ClassVar[str] = "id" + + MstInstances._item_type = MstInstancesItem + + class RapidPvstInstancesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"id": {"type": str}, "priority": {"type": int}, "_custom_data": {"type": dict}} + id: str + """ + "< vlan_id >, < vlan_id >-< vlan_id >" + Example: 105,202,505-506 + """ + priority: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: str | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RapidPvstInstancesItem. + + + Subclass of AvdModel. + + Args: + id: + "< vlan_id >, < vlan_id >-< vlan_id >" + Example: 105,202,505-506 + priority: priority + _custom_data: _custom_data + + """ + + class RapidPvstInstances(AvdIndexedList[str, RapidPvstInstancesItem]): + """Subclass of AvdIndexedList with `RapidPvstInstancesItem` items. Primary key is `id` (`str`).""" + + _primary_key: ClassVar[str] = "id" + + RapidPvstInstances._item_type = RapidPvstInstancesItem + + _fields: ClassVar[dict] = { + "root_super": {"type": bool}, + "edge_port": {"type": EdgePort}, + "mode": {"type": str}, + "bpduguard_rate_limit": {"type": BpduguardRateLimit}, + "rstp_priority": {"type": int}, + "mst": {"type": Mst}, + "mst_instances": {"type": MstInstances}, + "no_spanning_tree_vlan": {"type": str}, + "rapid_pvst_instances": {"type": RapidPvstInstances}, + "_custom_data": {"type": dict}, + } + root_super: bool | None + edge_port: EdgePort + """Subclass of AvdModel.""" + mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None + bpduguard_rate_limit: BpduguardRateLimit + """Subclass of AvdModel.""" + rstp_priority: int | None + mst: Mst + """Subclass of AvdModel.""" + mst_instances: MstInstances + """Subclass of AvdIndexedList with `MstInstancesItem` items. Primary key is `id` (`str`).""" + no_spanning_tree_vlan: str | None + """ + "< vlan_id >, < vlan_id >-< vlan_id >" + Example: 105,202,505-506 + """ + rapid_pvst_instances: RapidPvstInstances + """Subclass of AvdIndexedList with `RapidPvstInstancesItem` items. Primary key is `id` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + root_super: bool | None | UndefinedType = Undefined, + edge_port: EdgePort | UndefinedType = Undefined, + mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None | UndefinedType = Undefined, + bpduguard_rate_limit: BpduguardRateLimit | UndefinedType = Undefined, + rstp_priority: int | None | UndefinedType = Undefined, + mst: Mst | UndefinedType = Undefined, + mst_instances: MstInstances | UndefinedType = Undefined, + no_spanning_tree_vlan: str | None | UndefinedType = Undefined, + rapid_pvst_instances: RapidPvstInstances | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SpanningTree. + + + Subclass of AvdModel. + + Args: + root_super: root_super + edge_port: Subclass of AvdModel. + mode: mode + bpduguard_rate_limit: Subclass of AvdModel. + rstp_priority: rstp_priority + mst: Subclass of AvdModel. + mst_instances: Subclass of AvdIndexedList with `MstInstancesItem` items. Primary key is `id` (`str`). + no_spanning_tree_vlan: + "< vlan_id >, < vlan_id >-< vlan_id >" + Example: 105,202,505-506 + rapid_pvst_instances: Subclass of AvdIndexedList with `RapidPvstInstancesItem` items. Primary key is `id` (`str`). + _custom_data: _custom_data + + """ + + class StandardAccessListsItem(AvdModel): + """Subclass of AvdModel.""" + + class SequenceNumbersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"sequence": {"type": int}, "action": {"type": str}, "_custom_data": {"type": dict}} + sequence: int + """Sequence ID.""" + action: str + """ + Action as string. + Example: "deny ip any any" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sequence: int | UndefinedType = Undefined, + action: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceNumbersItem. + + + Subclass of AvdModel. + + Args: + sequence: Sequence ID. + action: + Action as string. + Example: "deny ip any any" + _custom_data: _custom_data + + """ + + class SequenceNumbers(AvdIndexedList[int, SequenceNumbersItem]): + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + + _primary_key: ClassVar[str] = "sequence" + + SequenceNumbers._item_type = SequenceNumbersItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "counters_per_entry": {"type": bool}, + "sequence_numbers": {"type": SequenceNumbers}, + "_custom_data": {"type": dict}, + } + name: str + """Access-list Name.""" + counters_per_entry: bool | None + sequence_numbers: SequenceNumbers + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + counters_per_entry: bool | None | UndefinedType = Undefined, + sequence_numbers: SequenceNumbers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StandardAccessListsItem. + + + Subclass of AvdModel. + + Args: + name: Access-list Name. + counters_per_entry: counters_per_entry + sequence_numbers: Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`). + _custom_data: _custom_data + + """ + + class StandardAccessLists(AvdIndexedList[str, StandardAccessListsItem]): + """Subclass of AvdIndexedList with `StandardAccessListsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + StandardAccessLists._item_type = StandardAccessListsItem + + class StaticRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "vrf": {"type": str}, + "destination_address_prefix": {"type": str}, + "interface": {"type": str}, + "gateway": {"type": str}, + "track_bfd": {"type": bool}, + "distance": {"type": int}, + "tag": {"type": int}, + "name": {"type": str}, + "metric": {"type": int}, + "_custom_data": {"type": dict}, + } + vrf: str | None + """VRF Name.""" + destination_address_prefix: str | None + """IPv4_network/Mask.""" + interface: str | None + gateway: str | None + """IPv4 Address.""" + track_bfd: bool | None + """Track next-hop using BFD.""" + distance: int | None + tag: int | None + name: str | None + """Description.""" + metric: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + vrf: str | None | UndefinedType = Undefined, + destination_address_prefix: str | None | UndefinedType = Undefined, + interface: str | None | UndefinedType = Undefined, + gateway: str | None | UndefinedType = Undefined, + track_bfd: bool | None | UndefinedType = Undefined, + distance: int | None | UndefinedType = Undefined, + tag: int | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + metric: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StaticRoutesItem. + + + Subclass of AvdModel. + + Args: + vrf: VRF Name. + destination_address_prefix: IPv4_network/Mask. + interface: interface + gateway: IPv4 Address. + track_bfd: Track next-hop using BFD. + distance: distance + tag: tag + name: Description. + metric: metric + _custom_data: _custom_data + + """ + + class StaticRoutes(AvdList[StaticRoutesItem]): + """Subclass of AvdList with `StaticRoutesItem` items.""" + + StaticRoutes._item_type = StaticRoutesItem + + class Stun(AvdModel): + """Subclass of AvdModel.""" + + class Client(AvdModel): + """Subclass of AvdModel.""" + + class ServerProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "ip_address": {"type": str}, + "ssl_profile": {"type": str}, + "port": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str + ip_address: str | None + ssl_profile: str | None + """SSL profile name.""" + port: int | None + """Destination port for the request STUN server (default - 3478).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + ssl_profile: str | None | UndefinedType = Undefined, + port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ServerProfilesItem. + + + Subclass of AvdModel. + + Args: + name: name + ip_address: ip_address + ssl_profile: SSL profile name. + port: Destination port for the request STUN server (default - 3478). + _custom_data: _custom_data + + """ + + class ServerProfiles(AvdIndexedList[str, ServerProfilesItem]): + """Subclass of AvdIndexedList with `ServerProfilesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + ServerProfiles._item_type = ServerProfilesItem + + _fields: ClassVar[dict] = {"server_profiles": {"type": ServerProfiles}, "_custom_data": {"type": dict}} + server_profiles: ServerProfiles + """ + List of server profiles for the client. + + Subclass of AvdIndexedList with `ServerProfilesItem` items. + Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, server_profiles: ServerProfiles | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Client. + + + Subclass of AvdModel. + + Args: + server_profiles: + List of server profiles for the client. + + Subclass of AvdIndexedList with `ServerProfilesItem` items. + Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class Server(AvdModel): + """Subclass of AvdModel.""" + + class LocalInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + LocalInterfaces._item_type = str + + class SslConnectionLifetime(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"minutes": {"type": int}, "hours": {"type": int}, "_custom_data": {"type": dict}} + minutes: int | None + """SSL connection lifetime in minutes (default - 120).""" + hours: int | None + """SSL connection lifetime in hours (default - 2).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + minutes: int | None | UndefinedType = Undefined, + hours: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SslConnectionLifetime. + + + Subclass of AvdModel. + + Args: + minutes: SSL connection lifetime in minutes (default - 120). + hours: SSL connection lifetime in hours (default - 2). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "local_interfaces": {"type": LocalInterfaces}, + "bindings_timeout": {"type": int}, + "ssl_profile": {"type": str}, + "ssl_connection_lifetime": {"type": SslConnectionLifetime}, + "port": {"type": int}, + "_custom_data": {"type": dict}, + } + local_interfaces: LocalInterfaces + """Subclass of AvdList with `str` items.""" + bindings_timeout: int | None + """Timeout for bindings stored on STUN server in seconds.""" + ssl_profile: str | None + """SSL profile name.""" + ssl_connection_lifetime: SslConnectionLifetime + """ + SSL connection lifetime in minutes or hours. + If both are specified, minutes is given higher + precedence. + + Subclass of AvdModel. + """ + port: int | None + """Listening port for STUN server (default - 3478).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + local_interfaces: LocalInterfaces | UndefinedType = Undefined, + bindings_timeout: int | None | UndefinedType = Undefined, + ssl_profile: str | None | UndefinedType = Undefined, + ssl_connection_lifetime: SslConnectionLifetime | UndefinedType = Undefined, + port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Server. + + + Subclass of AvdModel. + + Args: + local_interfaces: Subclass of AvdList with `str` items. + bindings_timeout: Timeout for bindings stored on STUN server in seconds. + ssl_profile: SSL profile name. + ssl_connection_lifetime: + SSL connection lifetime in minutes or hours. + If both are specified, minutes is given higher + precedence. + + Subclass of AvdModel. + port: Listening port for STUN server (default - 3478). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"client": {"type": Client}, "server": {"type": Server}, "_custom_data": {"type": dict}} + client: Client + """ + STUN client settings. + + Subclass of AvdModel. + """ + server: Server + """ + STUN server settings. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + client: Client | UndefinedType = Undefined, + server: Server | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Stun. + + + Subclass of AvdModel. + + Args: + client: + STUN client settings. + + Subclass of AvdModel. + server: + STUN server settings. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class SwitchportDefault(AvdModel): + """Subclass of AvdModel.""" + + class Phone(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"cos": {"type": int}, "trunk": {"type": str}, "vlan": {"type": int}, "_custom_data": {"type": dict}} + cos: int | None + trunk: Literal["tagged", "untagged"] | None + vlan: int | None + """VLAN ID.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + cos: int | None | UndefinedType = Undefined, + trunk: Literal["tagged", "untagged"] | None | UndefinedType = Undefined, + vlan: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Phone. + + + Subclass of AvdModel. + + Args: + cos: cos + trunk: trunk + vlan: VLAN ID. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"mode": {"type": str}, "phone": {"type": Phone}, "_custom_data": {"type": dict}} + mode: Literal["routed", "access"] | None + phone: Phone + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["routed", "access"] | None | UndefinedType = Undefined, + phone: Phone | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SwitchportDefault. + + + Subclass of AvdModel. + + Args: + mode: mode + phone: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class SwitchportPortSecurity(AvdModel): + """Subclass of AvdModel.""" + + class MacAddress(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"aging": {"type": bool}, "moveable": {"type": bool}, "_custom_data": {"type": dict}} + aging: bool | None + moveable: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + aging: bool | None | UndefinedType = Undefined, + moveable: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MacAddress. + + + Subclass of AvdModel. + + Args: + aging: aging + moveable: moveable + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "mac_address": {"type": MacAddress}, + "persistence_disabled": {"type": bool}, + "violation_protect_chip_based": {"type": bool}, + "_custom_data": {"type": dict}, + } + mac_address: MacAddress + """Subclass of AvdModel.""" + persistence_disabled: bool | None + violation_protect_chip_based: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mac_address: MacAddress | UndefinedType = Undefined, + persistence_disabled: bool | None | UndefinedType = Undefined, + violation_protect_chip_based: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SwitchportPortSecurity. + + + Subclass of AvdModel. + + Args: + mac_address: Subclass of AvdModel. + persistence_disabled: persistence_disabled + violation_protect_chip_based: violation_protect_chip_based + _custom_data: _custom_data + + """ + + class SyncE(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"network_option": {"type": int}, "_custom_data": {"type": dict}} + network_option: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, network_option: int | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + SyncE. + + + Subclass of AvdModel. + + Args: + network_option: network_option + _custom_data: _custom_data + + """ + + class System(AvdModel): + """Subclass of AvdModel.""" + + class ControlPlane(AvdModel): + """Subclass of AvdModel.""" + + class TcpMss(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4": {"type": int}, "ipv6": {"type": int}, "_custom_data": {"type": dict}} + ipv4: int | None + """Segment size.""" + ipv6: int | None + """Segment size.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4: int | None | UndefinedType = Undefined, + ipv6: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TcpMss. + + + Subclass of AvdModel. + + Args: + ipv4: Segment size. + ipv6: Segment size. + _custom_data: _custom_data + + """ + + class Ipv4AccessGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"acl_name": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + acl_name: str + vrf: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + acl_name: str | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4AccessGroupsItem. + + + Subclass of AvdModel. + + Args: + acl_name: acl_name + vrf: vrf + _custom_data: _custom_data + + """ + + class Ipv4AccessGroups(AvdList[Ipv4AccessGroupsItem]): + """Subclass of AvdList with `Ipv4AccessGroupsItem` items.""" + + Ipv4AccessGroups._item_type = Ipv4AccessGroupsItem + + class Ipv6AccessGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"acl_name": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + acl_name: str + vrf: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + acl_name: str | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6AccessGroupsItem. + + + Subclass of AvdModel. + + Args: + acl_name: acl_name + vrf: vrf + _custom_data: _custom_data + + """ + + class Ipv6AccessGroups(AvdList[Ipv6AccessGroupsItem]): + """Subclass of AvdList with `Ipv6AccessGroupsItem` items.""" + + Ipv6AccessGroups._item_type = Ipv6AccessGroupsItem + + _fields: ClassVar[dict] = { + "tcp_mss": {"type": TcpMss}, + "ipv4_access_group_ingress_default": {"type": str}, + "ipv4_access_groups": {"type": Ipv4AccessGroups}, + "ipv6_access_group_ingress_default": {"type": str}, + "ipv6_access_groups": {"type": Ipv6AccessGroups}, + "_custom_data": {"type": dict}, + } + tcp_mss: TcpMss + """Subclass of AvdModel.""" + ipv4_access_group_ingress_default: str | None + """ACL name to be used as the default CP ACL for all VRFs.""" + ipv4_access_groups: Ipv4AccessGroups + """Subclass of AvdList with `Ipv4AccessGroupsItem` items.""" + ipv6_access_group_ingress_default: str | None + """ACL name to be used as the default CP ACL for all VRFs.""" + ipv6_access_groups: Ipv6AccessGroups + """Subclass of AvdList with `Ipv6AccessGroupsItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + tcp_mss: TcpMss | UndefinedType = Undefined, + ipv4_access_group_ingress_default: str | None | UndefinedType = Undefined, + ipv4_access_groups: Ipv4AccessGroups | UndefinedType = Undefined, + ipv6_access_group_ingress_default: str | None | UndefinedType = Undefined, + ipv6_access_groups: Ipv6AccessGroups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ControlPlane. + + + Subclass of AvdModel. + + Args: + tcp_mss: Subclass of AvdModel. + ipv4_access_group_ingress_default: ACL name to be used as the default CP ACL for all VRFs. + ipv4_access_groups: Subclass of AvdList with `Ipv4AccessGroupsItem` items. + ipv6_access_group_ingress_default: ACL name to be used as the default CP ACL for all VRFs. + ipv6_access_groups: Subclass of AvdList with `Ipv6AccessGroupsItem` items. + _custom_data: _custom_data + + """ + + class L1(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "unsupported_speed_action": {"type": str}, + "unsupported_error_correction_action": {"type": str}, + "_custom_data": {"type": dict}, + } + unsupported_speed_action: Literal["error", "warn"] | None + unsupported_error_correction_action: Literal["error", "warn"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + unsupported_speed_action: Literal["error", "warn"] | None | UndefinedType = Undefined, + unsupported_error_correction_action: Literal["error", "warn"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L1. + + + Subclass of AvdModel. + + Args: + unsupported_speed_action: unsupported_speed_action + unsupported_error_correction_action: unsupported_error_correction_action + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"control_plane": {"type": ControlPlane}, "l1": {"type": L1}, "_custom_data": {"type": dict}} + control_plane: ControlPlane + """Subclass of AvdModel.""" + l1: L1 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + control_plane: ControlPlane | UndefinedType = Undefined, + l1: L1 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + System. + + + Subclass of AvdModel. + + Args: + control_plane: Subclass of AvdModel. + l1: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class TacacsServers(AvdModel): + """Subclass of AvdModel.""" + + class HostsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "host": {"type": str}, + "vrf": {"type": str}, + "key": {"type": str}, + "key_type": {"type": str, "default": "7"}, + "single_connection": {"type": bool}, + "timeout": {"type": int}, + "_custom_data": {"type": dict}, + } + host: str | None + """Host IP address or name.""" + vrf: str | None + key: str | None + """Encrypted key.""" + key_type: Literal["0", "7", "8a"] + """Default value: `"7"`""" + single_connection: bool | None + timeout: int | None + """Timeout in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + host: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + key_type: Literal["0", "7", "8a"] | UndefinedType = Undefined, + single_connection: bool | None | UndefinedType = Undefined, + timeout: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + HostsItem. + + + Subclass of AvdModel. + + Args: + host: Host IP address or name. + vrf: vrf + key: Encrypted key. + key_type: key_type + single_connection: single_connection + timeout: Timeout in seconds. + _custom_data: _custom_data + + """ + + class Hosts(AvdList[HostsItem]): + """Subclass of AvdList with `HostsItem` items.""" + + Hosts._item_type = HostsItem + + _fields: ClassVar[dict] = { + "timeout": {"type": int}, + "hosts": {"type": Hosts}, + "policy_unknown_mandatory_attribute_ignore": {"type": bool}, + "_custom_data": {"type": dict}, + } + timeout: int | None + """Timeout in seconds.""" + hosts: Hosts + """Subclass of AvdList with `HostsItem` items.""" + policy_unknown_mandatory_attribute_ignore: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + timeout: int | None | UndefinedType = Undefined, + hosts: Hosts | UndefinedType = Undefined, + policy_unknown_mandatory_attribute_ignore: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TacacsServers. + + + Subclass of AvdModel. + + Args: + timeout: Timeout in seconds. + hosts: Subclass of AvdList with `HostsItem` items. + policy_unknown_mandatory_attribute_ignore: policy_unknown_mandatory_attribute_ignore + _custom_data: _custom_data + + """ + + class TapAggregation(AvdModel): + """Subclass of AvdModel.""" + + class Mode(AvdModel): + """Subclass of AvdModel.""" + + class Exclusive(AvdModel): + """Subclass of AvdModel.""" + + class NoErrdisable(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + NoErrdisable._item_type = str + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "profile": {"type": str}, + "no_errdisable": {"type": NoErrdisable}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + profile: str | None + """Profile Name.""" + no_errdisable: NoErrdisable + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + profile: str | None | UndefinedType = Undefined, + no_errdisable: NoErrdisable | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Exclusive. + + + Subclass of AvdModel. + + Args: + enabled: enabled + profile: Profile Name. + no_errdisable: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"exclusive": {"type": Exclusive}, "_custom_data": {"type": dict}} + exclusive: Exclusive + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, exclusive: Exclusive | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Mode. + + + Subclass of AvdModel. + + Args: + exclusive: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Mac(AvdModel): + """Subclass of AvdModel.""" + + class Timestamp(AvdModel): + """Subclass of AvdModel.""" + + class Header(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"format": {"type": str}, "eth_type": {"type": int}, "_custom_data": {"type": dict}} + format: Literal["48-bit", "64-bit"] | None + eth_type: int | None + """EtherType.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + format: Literal["48-bit", "64-bit"] | None | UndefinedType = Undefined, + eth_type: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Header. + + + Subclass of AvdModel. + + Args: + format: format + eth_type: EtherType. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"replace_source_mac": {"type": bool}, "header": {"type": Header}, "_custom_data": {"type": dict}} + replace_source_mac: bool | None + header: Header + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + replace_source_mac: bool | None | UndefinedType = Undefined, + header: Header | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Timestamp. + + + Subclass of AvdModel. + + Args: + replace_source_mac: replace_source_mac + header: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "timestamp": {"type": Timestamp}, + "fcs_append": {"type": bool}, + "fcs_error": {"type": str}, + "_custom_data": {"type": dict}, + } + timestamp: Timestamp + """ + mac.timestamp.replace_source_mac and mac.timestamp.header.format are mutually exclsuive. If both are + defined, replace_source_mac takes precedence. + + + Subclass of AvdModel. + """ + fcs_append: bool | None + """ + mac.fcs_append and mac.fcs_error are mutually exclusive. If both are defined, mac.fcs_append takes + precedence. + """ + fcs_error: Literal["correct", "discard", "pass-through"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + timestamp: Timestamp | UndefinedType = Undefined, + fcs_append: bool | None | UndefinedType = Undefined, + fcs_error: Literal["correct", "discard", "pass-through"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Mac. + + + Subclass of AvdModel. + + Args: + timestamp: + mac.timestamp.replace_source_mac and mac.timestamp.header.format are mutually exclsuive. If both are + defined, replace_source_mac takes precedence. + + + Subclass of AvdModel. + fcs_append: + mac.fcs_append and mac.fcs_error are mutually exclusive. If both are defined, mac.fcs_append takes + precedence. + fcs_error: fcs_error + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "mode": {"type": Mode}, + "encapsulation_dot1br_strip": {"type": bool}, + "encapsulation_vn_tag_strip": {"type": bool}, + "protocol_lldp_trap": {"type": bool}, + "truncation_size": {"type": int}, + "mac": {"type": Mac}, + "_custom_data": {"type": dict}, + } + mode: Mode + """Subclass of AvdModel.""" + encapsulation_dot1br_strip: bool | None + encapsulation_vn_tag_strip: bool | None + protocol_lldp_trap: bool | None + truncation_size: int | None + """Allowed truncation_size values vary depending on the platform.""" + mac: Mac + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Mode | UndefinedType = Undefined, + encapsulation_dot1br_strip: bool | None | UndefinedType = Undefined, + encapsulation_vn_tag_strip: bool | None | UndefinedType = Undefined, + protocol_lldp_trap: bool | None | UndefinedType = Undefined, + truncation_size: int | None | UndefinedType = Undefined, + mac: Mac | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TapAggregation. + + + Subclass of AvdModel. + + Args: + mode: Subclass of AvdModel. + encapsulation_dot1br_strip: encapsulation_dot1br_strip + encapsulation_vn_tag_strip: encapsulation_vn_tag_strip + protocol_lldp_trap: protocol_lldp_trap + truncation_size: Allowed truncation_size values vary depending on the platform. + mac: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class TcamProfile(AvdModel): + """Subclass of AvdModel.""" + + class ProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "config": {"type": str}, "source": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Tcam-Profile Name.""" + config: str | None + """ + TCAM Profile Config. Since these can be very long, it is often a good idea to import the config from + a file. + Example: "{{ lookup('file', 'TCAM_TRAFFIC_POLICY.conf') }}" + """ + source: str | None + """ + TCAM profile local source path. Used to read the TCAM profile from a local path existing on the + device. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + config: str | None | UndefinedType = Undefined, + source: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ProfilesItem. + + + Subclass of AvdModel. + + Args: + name: Tcam-Profile Name. + config: + TCAM Profile Config. Since these can be very long, it is often a good idea to import the config from + a file. + Example: "{{ lookup('file', 'TCAM_TRAFFIC_POLICY.conf') }}" + source: + TCAM profile local source path. Used to read the TCAM profile from a local path existing on the + device. + _custom_data: _custom_data + + """ + + class Profiles(AvdIndexedList[str, ProfilesItem]): + """Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Profiles._item_type = ProfilesItem + + _fields: ClassVar[dict] = {"system": {"type": str}, "profiles": {"type": Profiles}, "_custom_data": {"type": dict}} + system: str | None + """TCAM profile name to activate.""" + profiles: Profiles + """Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + system: str | None | UndefinedType = Undefined, + profiles: Profiles | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TcamProfile. + + + Subclass of AvdModel. + + Args: + system: TCAM profile name to activate. + profiles: Subclass of AvdIndexedList with `ProfilesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class Terminal(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"length": {"type": int}, "width": {"type": int}, "_custom_data": {"type": dict}} + length: int | None + width: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + length: int | None | UndefinedType = Undefined, + width: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Terminal. + + + Subclass of AvdModel. + + Args: + length: length + width: width + _custom_data: _custom_data + + """ + + class TrackersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "interface": {"type": str}, + "tracked_property": {"type": str, "default": "line-protocol"}, + "_custom_data": {"type": dict}, + } + name: str + """Name of tracker object.""" + interface: str + """Name of tracked interface.""" + tracked_property: str + """ + Property to track. + + Default value: `"line-protocol"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + interface: str | UndefinedType = Undefined, + tracked_property: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TrackersItem. + + + Subclass of AvdModel. + + Args: + name: Name of tracker object. + interface: Name of tracked interface. + tracked_property: Property to track. + _custom_data: _custom_data + + """ + + class Trackers(AvdIndexedList[str, TrackersItem]): + """Subclass of AvdIndexedList with `TrackersItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Trackers._item_type = TrackersItem + + class TrafficPolicies(AvdModel): + """Subclass of AvdModel.""" + + class Options(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"counter_per_interface": {"type": bool}, "_custom_data": {"type": dict}} + counter_per_interface: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, counter_per_interface: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Options. + + + Subclass of AvdModel. + + Args: + counter_per_interface: counter_per_interface + _custom_data: _custom_data + + """ + + class FieldSets(AvdModel): + """Subclass of AvdModel.""" + + class Ipv4Item(AvdModel): + """Subclass of AvdModel.""" + + class Prefixes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Prefixes._item_type = str + + _fields: ClassVar[dict] = {"name": {"type": str}, "prefixes": {"type": Prefixes}, "_custom_data": {"type": dict}} + name: str + """IPv4 Prefix Field Set Name.""" + prefixes: Prefixes + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + prefixes: Prefixes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4Item. + + + Subclass of AvdModel. + + Args: + name: IPv4 Prefix Field Set Name. + prefixes: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class Ipv4(AvdIndexedList[str, Ipv4Item]): + """Subclass of AvdIndexedList with `Ipv4Item` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Ipv4._item_type = Ipv4Item + + class Ipv6Item(AvdModel): + """Subclass of AvdModel.""" + + class Prefixes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Prefixes._item_type = str + + _fields: ClassVar[dict] = {"name": {"type": str}, "prefixes": {"type": Prefixes}, "_custom_data": {"type": dict}} + name: str + """IPv6 Prefix Field Set Name.""" + prefixes: Prefixes + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + prefixes: Prefixes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6Item. + + + Subclass of AvdModel. + + Args: + name: IPv6 Prefix Field Set Name. + prefixes: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class Ipv6(AvdIndexedList[str, Ipv6Item]): + """Subclass of AvdIndexedList with `Ipv6Item` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Ipv6._item_type = Ipv6Item + + class PortsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "port_range": {"type": str}, "_custom_data": {"type": dict}} + name: str + """L4 Port Field Set Name.""" + port_range: str | None + """Example: '10,20,80,440-450'""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + port_range: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PortsItem. + + + Subclass of AvdModel. + + Args: + name: L4 Port Field Set Name. + port_range: Example: '10,20,80,440-450' + _custom_data: _custom_data + + """ + + class Ports(AvdIndexedList[str, PortsItem]): + """Subclass of AvdIndexedList with `PortsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Ports._item_type = PortsItem + + _fields: ClassVar[dict] = {"ipv4": {"type": Ipv4}, "ipv6": {"type": Ipv6}, "ports": {"type": Ports}, "_custom_data": {"type": dict}} + ipv4: Ipv4 + """Subclass of AvdIndexedList with `Ipv4Item` items. Primary key is `name` (`str`).""" + ipv6: Ipv6 + """Subclass of AvdIndexedList with `Ipv6Item` items. Primary key is `name` (`str`).""" + ports: Ports + """Subclass of AvdIndexedList with `PortsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4: Ipv4 | UndefinedType = Undefined, + ipv6: Ipv6 | UndefinedType = Undefined, + ports: Ports | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FieldSets. + + + Subclass of AvdModel. + + Args: + ipv4: Subclass of AvdIndexedList with `Ipv4Item` items. Primary key is `name` (`str`). + ipv6: Subclass of AvdIndexedList with `Ipv6Item` items. Primary key is `name` (`str`). + ports: Subclass of AvdIndexedList with `PortsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class PoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + class MatchesItem(AvdModel): + """Subclass of AvdModel.""" + + class Source(AvdModel): + """Subclass of AvdModel.""" + + class Prefixes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Prefixes._item_type = str + + class PrefixLists(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + PrefixLists._item_type = str + + _fields: ClassVar[dict] = {"prefixes": {"type": Prefixes}, "prefix_lists": {"type": PrefixLists}, "_custom_data": {"type": dict}} + prefixes: Prefixes + """Subclass of AvdList with `str` items.""" + prefix_lists: PrefixLists + """ + Field-set prefix lists. + + Subclass of AvdList with `str` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefixes: Prefixes | UndefinedType = Undefined, + prefix_lists: PrefixLists | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Source. + + + Subclass of AvdModel. + + Args: + prefixes: Subclass of AvdList with `str` items. + prefix_lists: + Field-set prefix lists. + + Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class Destination(AvdModel): + """Subclass of AvdModel.""" + + class Prefixes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Prefixes._item_type = str + + class PrefixLists(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + PrefixLists._item_type = str + + _fields: ClassVar[dict] = {"prefixes": {"type": Prefixes}, "prefix_lists": {"type": PrefixLists}, "_custom_data": {"type": dict}} + prefixes: Prefixes + """Subclass of AvdList with `str` items.""" + prefix_lists: PrefixLists + """ + Field-set prefix lists. + + Subclass of AvdList with `str` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + prefixes: Prefixes | UndefinedType = Undefined, + prefix_lists: PrefixLists | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Destination. + + + Subclass of AvdModel. + + Args: + prefixes: Subclass of AvdList with `str` items. + prefix_lists: + Field-set prefix lists. + + Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class Fragment(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"offset": {"type": str}, "_custom_data": {"type": dict}} + offset: str | None + """Fragment offset range.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, offset: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Fragment. + + + Subclass of AvdModel. + + Args: + offset: Fragment offset range. + _custom_data: _custom_data + + """ + + class ProtocolsItem(AvdModel): + """Subclass of AvdModel.""" + + class Flags(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Flags._item_type = str + + class IcmpType(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + IcmpType._item_type = str + + _fields: ClassVar[dict] = { + "protocol": {"type": str}, + "src_port": {"type": str}, + "dst_port": {"type": str}, + "src_field": {"type": str}, + "dst_field": {"type": str}, + "flags": {"type": Flags}, + "icmp_type": {"type": IcmpType}, + "enforce_gtsm": {"type": bool}, + "_custom_data": {"type": dict}, + } + protocol: str + src_port: str | None + """Port range.""" + dst_port: str | None + """Port range.""" + src_field: str | None + """L4 port range field set.""" + dst_field: str | None + """L4 port range field set.""" + flags: Flags + """Subclass of AvdList with `str` items.""" + icmp_type: IcmpType + """Subclass of AvdList with `str` items.""" + enforce_gtsm: bool | None + """Enforce the GTSM for BGP speakers. Only supported when protocol is set to 'neighbors'.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + protocol: str | UndefinedType = Undefined, + src_port: str | None | UndefinedType = Undefined, + dst_port: str | None | UndefinedType = Undefined, + src_field: str | None | UndefinedType = Undefined, + dst_field: str | None | UndefinedType = Undefined, + flags: Flags | UndefinedType = Undefined, + icmp_type: IcmpType | UndefinedType = Undefined, + enforce_gtsm: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ProtocolsItem. + + + Subclass of AvdModel. + + Args: + protocol: protocol + src_port: Port range. + dst_port: Port range. + src_field: L4 port range field set. + dst_field: L4 port range field set. + flags: Subclass of AvdList with `str` items. + icmp_type: Subclass of AvdList with `str` items. + enforce_gtsm: Enforce the GTSM for BGP speakers. Only supported when protocol is set to 'neighbors'. + _custom_data: _custom_data + + """ + + class Protocols(AvdIndexedList[str, ProtocolsItem]): + """Subclass of AvdIndexedList with `ProtocolsItem` items. Primary key is `protocol` (`str`).""" + + _primary_key: ClassVar[str] = "protocol" + + Protocols._item_type = ProtocolsItem + + class Actions(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "dscp": {"type": int}, + "traffic_class": {"type": int}, + "count": {"type": str}, + "drop": {"type": bool}, + "log": {"type": bool}, + "_custom_data": {"type": dict}, + } + dscp: int | None + traffic_class: int | None + """Traffic class ID.""" + count: str | None + """Counter name.""" + drop: bool | None + log: bool | None + """Only supported when action is set to drop.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dscp: int | None | UndefinedType = Undefined, + traffic_class: int | None | UndefinedType = Undefined, + count: str | None | UndefinedType = Undefined, + drop: bool | None | UndefinedType = Undefined, + log: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Actions. + + + Subclass of AvdModel. + + Args: + dscp: dscp + traffic_class: Traffic class ID. + count: Counter name. + drop: drop + log: Only supported when action is set to drop. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "type": {"type": str}, + "source": {"type": Source}, + "destination": {"type": Destination}, + "ttl": {"type": str}, + "fragment": {"type": Fragment}, + "protocols": {"type": Protocols}, + "actions": {"type": Actions}, + "_custom_data": {"type": dict}, + } + name: str + """Traffic Policy Item.""" + type: Literal["ipv4", "ipv6"] + source: Source + """Subclass of AvdModel.""" + destination: Destination + """Subclass of AvdModel.""" + ttl: str | None + """TTL range.""" + fragment: Fragment + """ + The 'fragment' command is not supported when 'source port' + or 'destination port' command is + configured. + + + Subclass of AvdModel. + """ + protocols: Protocols + """Subclass of AvdIndexedList with `ProtocolsItem` items. Primary key is `protocol` (`str`).""" + actions: Actions + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + type: Literal["ipv4", "ipv6"] | UndefinedType = Undefined, + source: Source | UndefinedType = Undefined, + destination: Destination | UndefinedType = Undefined, + ttl: str | None | UndefinedType = Undefined, + fragment: Fragment | UndefinedType = Undefined, + protocols: Protocols | UndefinedType = Undefined, + actions: Actions | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MatchesItem. + + + Subclass of AvdModel. + + Args: + name: Traffic Policy Item. + type: type + source: Subclass of AvdModel. + destination: Subclass of AvdModel. + ttl: TTL range. + fragment: + The 'fragment' command is not supported when 'source port' + or 'destination port' command is + configured. + + + Subclass of AvdModel. + protocols: Subclass of AvdIndexedList with `ProtocolsItem` items. Primary key is `protocol` (`str`). + actions: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Matches(AvdIndexedList[str, MatchesItem]): + """Subclass of AvdIndexedList with `MatchesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Matches._item_type = MatchesItem + + class DefaultActions(AvdModel): + """Subclass of AvdModel.""" + + class Ipv4(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "dscp": {"type": int}, + "traffic_class": {"type": int}, + "count": {"type": str}, + "drop": {"type": bool}, + "log": {"type": bool}, + "_custom_data": {"type": dict}, + } + dscp: int | None + traffic_class: int | None + """Traffic class ID.""" + count: str | None + """Counter name.""" + drop: bool | None + log: bool | None + """Only supported when action is set to drop.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dscp: int | None | UndefinedType = Undefined, + traffic_class: int | None | UndefinedType = Undefined, + count: str | None | UndefinedType = Undefined, + drop: bool | None | UndefinedType = Undefined, + log: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4. + + + Subclass of AvdModel. + + Args: + dscp: dscp + traffic_class: Traffic class ID. + count: Counter name. + drop: drop + log: Only supported when action is set to drop. + _custom_data: _custom_data + + """ + + class Ipv6(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "dscp": {"type": int}, + "traffic_class": {"type": int}, + "count": {"type": str}, + "drop": {"type": bool}, + "log": {"type": bool}, + "_custom_data": {"type": dict}, + } + dscp: int | None + traffic_class: int | None + """Traffic class ID.""" + count: str | None + """Counter name.""" + drop: bool | None + log: bool | None + """Only supported when action is set to drop.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dscp: int | None | UndefinedType = Undefined, + traffic_class: int | None | UndefinedType = Undefined, + count: str | None | UndefinedType = Undefined, + drop: bool | None | UndefinedType = Undefined, + log: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6. + + + Subclass of AvdModel. + + Args: + dscp: dscp + traffic_class: Traffic class ID. + count: Counter name. + drop: drop + log: Only supported when action is set to drop. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ipv4": {"type": Ipv4}, "ipv6": {"type": Ipv6}, "_custom_data": {"type": dict}} + ipv4: Ipv4 + """Subclass of AvdModel.""" + ipv6: Ipv6 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4: Ipv4 | UndefinedType = Undefined, + ipv6: Ipv6 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultActions. + + + Subclass of AvdModel. + + Args: + ipv4: Subclass of AvdModel. + ipv6: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "matches": {"type": Matches}, + "default_actions": {"type": DefaultActions}, + "_custom_data": {"type": dict}, + } + name: str + """Traffic Policy Name.""" + matches: Matches + """Subclass of AvdIndexedList with `MatchesItem` items. Primary key is `name` (`str`).""" + default_actions: DefaultActions + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + matches: Matches | UndefinedType = Undefined, + default_actions: DefaultActions | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PoliciesItem. + + + Subclass of AvdModel. + + Args: + name: Traffic Policy Name. + matches: Subclass of AvdIndexedList with `MatchesItem` items. Primary key is `name` (`str`). + default_actions: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Policies(AvdIndexedList[str, PoliciesItem]): + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Policies._item_type = PoliciesItem + + _fields: ClassVar[dict] = { + "options": {"type": Options}, + "field_sets": {"type": FieldSets}, + "policies": {"type": Policies}, + "_custom_data": {"type": dict}, + } + options: Options + """Subclass of AvdModel.""" + field_sets: FieldSets + """Subclass of AvdModel.""" + policies: Policies + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + options: Options | UndefinedType = Undefined, + field_sets: FieldSets | UndefinedType = Undefined, + policies: Policies | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TrafficPolicies. + + + Subclass of AvdModel. + + Args: + options: Subclass of AvdModel. + field_sets: Subclass of AvdModel. + policies: Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class TunnelInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class TcpMssCeiling(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4": {"type": int}, "ipv6": {"type": int}, "direction": {"type": str}, "_custom_data": {"type": dict}} + ipv4: int | None + """Segment Size for IPv4.""" + ipv6: int | None + """Segment Size for IPv6.""" + direction: Literal["ingress", "egress"] | None + """Optional direction ('ingress', 'egress') for tcp mss ceiling.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4: int | None | UndefinedType = Undefined, + ipv6: int | None | UndefinedType = Undefined, + direction: Literal["ingress", "egress"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TcpMssCeiling. + + + Subclass of AvdModel. + + Args: + ipv4: Segment Size for IPv4. + ipv6: Segment Size for IPv6. + direction: Optional direction ('ingress', 'egress') for tcp mss ceiling. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "description": {"type": str}, + "shutdown": {"type": bool}, + "mtu": {"type": int}, + "vrf": {"type": str}, + "underlay_vrf": {"type": str}, + "ip_address": {"type": str}, + "ipv6_enable": {"type": bool}, + "ipv6_address": {"type": str}, + "access_group_in": {"type": str}, + "access_group_out": {"type": str}, + "ipv6_access_group_in": {"type": str}, + "ipv6_access_group_out": {"type": str}, + "tcp_mss_ceiling": {"type": TcpMssCeiling}, + "tunnel_mode": {"type": str}, + "source_interface": {"type": str}, + "destination": {"type": str}, + "path_mtu_discovery": {"type": bool}, + "ipsec_profile": {"type": str}, + "nat_profile": {"type": str}, + "eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Tunnel Interface Name.""" + description: str | None + shutdown: bool | None + mtu: int | None + vrf: str | None + """VRF Name.""" + underlay_vrf: str | None + """Underlay VRF Name.""" + ip_address: str | None + """IPv4_address/Mask.""" + ipv6_enable: bool | None + ipv6_address: str | None + """IPv6_address/Mask.""" + access_group_in: str | None + """IPv4 ACL Name for ingress.""" + access_group_out: str | None + """IPv4 ACL Name for egress.""" + ipv6_access_group_in: str | None + """IPv6 ACL Name for ingress.""" + ipv6_access_group_out: str | None + """IPv6 ACL Name for egress.""" + tcp_mss_ceiling: TcpMssCeiling + """Subclass of AvdModel.""" + tunnel_mode: Literal["gre", "ipsec"] | None + """ + Tunnel encapsulation method. + `gre`: Generic route encapsulation protocol, + `ipsec`: IPsec-over-IP + encapsulation. + """ + source_interface: str | None + """Tunnel Source Interface Name.""" + destination: str | None + """IPv4 or IPv6 Address Tunnel Destination.""" + path_mtu_discovery: bool | None + """Enable Path MTU Discovery On Tunnel.""" + ipsec_profile: str | None + """ + Used only when `tunnel_mode` is set to `ipsec`. + It must target a defined IPsec profile. + """ + nat_profile: str | None + """NAT interface profile.""" + eos_cli: str | None + """ + Multiline String with EOS CLI rendered directly on the Tunnel interface in the final EOS + configuration. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + underlay_vrf: str | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + ipv6_enable: bool | None | UndefinedType = Undefined, + ipv6_address: str | None | UndefinedType = Undefined, + access_group_in: str | None | UndefinedType = Undefined, + access_group_out: str | None | UndefinedType = Undefined, + ipv6_access_group_in: str | None | UndefinedType = Undefined, + ipv6_access_group_out: str | None | UndefinedType = Undefined, + tcp_mss_ceiling: TcpMssCeiling | UndefinedType = Undefined, + tunnel_mode: Literal["gre", "ipsec"] | None | UndefinedType = Undefined, + source_interface: str | None | UndefinedType = Undefined, + destination: str | None | UndefinedType = Undefined, + path_mtu_discovery: bool | None | UndefinedType = Undefined, + ipsec_profile: str | None | UndefinedType = Undefined, + nat_profile: str | None | UndefinedType = Undefined, + eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TunnelInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: Tunnel Interface Name. + description: description + shutdown: shutdown + mtu: mtu + vrf: VRF Name. + underlay_vrf: Underlay VRF Name. + ip_address: IPv4_address/Mask. + ipv6_enable: ipv6_enable + ipv6_address: IPv6_address/Mask. + access_group_in: IPv4 ACL Name for ingress. + access_group_out: IPv4 ACL Name for egress. + ipv6_access_group_in: IPv6 ACL Name for ingress. + ipv6_access_group_out: IPv6 ACL Name for egress. + tcp_mss_ceiling: Subclass of AvdModel. + tunnel_mode: + Tunnel encapsulation method. + `gre`: Generic route encapsulation protocol, + `ipsec`: IPsec-over-IP + encapsulation. + source_interface: Tunnel Source Interface Name. + destination: IPv4 or IPv6 Address Tunnel Destination. + path_mtu_discovery: Enable Path MTU Discovery On Tunnel. + ipsec_profile: + Used only when `tunnel_mode` is set to `ipsec`. + It must target a defined IPsec profile. + nat_profile: NAT interface profile. + eos_cli: + Multiline String with EOS CLI rendered directly on the Tunnel interface in the final EOS + configuration. + _custom_data: _custom_data + + """ + + class TunnelInterfaces(AvdIndexedList[str, TunnelInterfacesItem]): + """Subclass of AvdIndexedList with `TunnelInterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + TunnelInterfaces._item_type = TunnelInterfacesItem + + class VirtualSourceNatVrfsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "ip_address": {"type": str}, "ipv6_address": {"type": str}, "_custom_data": {"type": dict}} + name: str + """VRF Name.""" + ip_address: str | None + """IPv4 Address.""" + ipv6_address: str | None + """IPv6 Address.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + ipv6_address: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VirtualSourceNatVrfsItem. + + + Subclass of AvdModel. + + Args: + name: VRF Name. + ip_address: IPv4 Address. + ipv6_address: IPv6 Address. + _custom_data: _custom_data + + """ + + class VirtualSourceNatVrfs(AvdIndexedList[str, VirtualSourceNatVrfsItem]): + """Subclass of AvdIndexedList with `VirtualSourceNatVrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + VirtualSourceNatVrfs._item_type = VirtualSourceNatVrfsItem + + class VlanInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Logging(AvdModel): + """Subclass of AvdModel.""" + + class Event(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"link_status": {"type": bool}, "_custom_data": {"type": dict}} + link_status: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, link_status: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Event. + + + Subclass of AvdModel. + + Args: + link_status: link_status + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"event": {"type": Event}, "_custom_data": {"type": dict}} + event: Event + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, event: Event | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Logging. + + + Subclass of AvdModel. + + Args: + event: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class IpAddressSecondaries(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + IpAddressSecondaries._item_type = str + + class IpVirtualRouterAddresses(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + IpVirtualRouterAddresses._item_type = str + + class IpAddressVirtualSecondaries(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + IpAddressVirtualSecondaries._item_type = str + + class IpIgmpHostProxy(AvdModel): + """Subclass of AvdModel.""" + + class GroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class ExcludeItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"source": {"type": str}, "_custom_data": {"type": dict}} + source: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, source: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + ExcludeItem. + + + Subclass of AvdModel. + + Args: + source: source + _custom_data: _custom_data + + """ + + class Exclude(AvdIndexedList[str, ExcludeItem]): + """Subclass of AvdIndexedList with `ExcludeItem` items. Primary key is `source` (`str`).""" + + _primary_key: ClassVar[str] = "source" + + Exclude._item_type = ExcludeItem + + class IncludeItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"source": {"type": str}, "_custom_data": {"type": dict}} + source: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, source: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + IncludeItem. + + + Subclass of AvdModel. + + Args: + source: source + _custom_data: _custom_data + + """ + + class Include(AvdIndexedList[str, IncludeItem]): + """Subclass of AvdIndexedList with `IncludeItem` items. Primary key is `source` (`str`).""" + + _primary_key: ClassVar[str] = "source" + + Include._item_type = IncludeItem + + _fields: ClassVar[dict] = {"group": {"type": str}, "exclude": {"type": Exclude}, "include": {"type": Include}, "_custom_data": {"type": dict}} + group: str + """Multicast Address.""" + exclude: Exclude + """ + The same source must not be present both in `exclude` and `include` list. + + Subclass of + AvdIndexedList with `ExcludeItem` items. Primary key is `source` (`str`). + """ + include: Include + """ + The same source must not be present both in `exclude` and `include` list. + + Subclass of + AvdIndexedList with `IncludeItem` items. Primary key is `source` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + group: str | UndefinedType = Undefined, + exclude: Exclude | UndefinedType = Undefined, + include: Include | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GroupsItem. + + + Subclass of AvdModel. + + Args: + group: Multicast Address. + exclude: + The same source must not be present both in `exclude` and `include` list. + + Subclass of + AvdIndexedList with `ExcludeItem` items. Primary key is `source` (`str`). + include: + The same source must not be present both in `exclude` and `include` list. + + Subclass of + AvdIndexedList with `IncludeItem` items. Primary key is `source` (`str`). + _custom_data: _custom_data + + """ + + class Groups(AvdIndexedList[str, GroupsItem]): + """Subclass of AvdIndexedList with `GroupsItem` items. Primary key is `group` (`str`).""" + + _primary_key: ClassVar[str] = "group" + + Groups._item_type = GroupsItem + + class AccessListsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "_custom_data": {"type": dict}} + name: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, name: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + AccessListsItem. + + + Subclass of AvdModel. + + Args: + name: name + _custom_data: _custom_data + + """ + + class AccessLists(AvdIndexedList[str, AccessListsItem]): + """Subclass of AvdIndexedList with `AccessListsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + AccessLists._item_type = AccessListsItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "groups": {"type": Groups}, + "report_interval": {"type": int}, + "access_lists": {"type": AccessLists}, + "version": {"type": int}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + groups: Groups + """Subclass of AvdIndexedList with `GroupsItem` items. Primary key is `group` (`str`).""" + report_interval: int | None + """Time interval between unsolicited reports.""" + access_lists: AccessLists + """ + Non-standard Access List name. + + Subclass of AvdIndexedList with `AccessListsItem` items. Primary key + is `name` (`str`). + """ + version: int | None + """IGMP version on IGMP host-proxy interface.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + report_interval: int | None | UndefinedType = Undefined, + access_lists: AccessLists | UndefinedType = Undefined, + version: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpIgmpHostProxy. + + + Subclass of AvdModel. + + Args: + enabled: enabled + groups: Subclass of AvdIndexedList with `GroupsItem` items. Primary key is `group` (`str`). + report_interval: Time interval between unsolicited reports. + access_lists: + Non-standard Access List name. + + Subclass of AvdIndexedList with `AccessListsItem` items. Primary key + is `name` (`str`). + version: IGMP version on IGMP host-proxy interface. + _custom_data: _custom_data + + """ + + class IpHelpersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ip_helper": {"type": str}, "source_interface": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + ip_helper: str + """IP address or hostname of DHCP server.""" + source_interface: str | None + """Interface used as source for forwarded DHCP packets.""" + vrf: str | None + """VRF where DHCP server can be reached.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_helper: str | UndefinedType = Undefined, + source_interface: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpHelpersItem. + + + Subclass of AvdModel. + + Args: + ip_helper: IP address or hostname of DHCP server. + source_interface: Interface used as source for forwarded DHCP packets. + vrf: VRF where DHCP server can be reached. + _custom_data: _custom_data + + """ + + class IpHelpers(AvdIndexedList[str, IpHelpersItem]): + """Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is `ip_helper` (`str`).""" + + _primary_key: ClassVar[str] = "ip_helper" + + IpHelpers._item_type = IpHelpersItem + + class IpNat(AvdModel): + """Subclass of AvdModel.""" + + class Destination(AvdModel): + """Subclass of AvdModel.""" + + class DynamicItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "access_list": {"type": str}, + "comment": {"type": str}, + "pool_name": {"type": str}, + "priority": {"type": int}, + "_custom_data": {"type": dict}, + } + access_list: str + comment: str | None + pool_name: str + priority: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + access_list: str | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + pool_name: str | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DynamicItem. + + + Subclass of AvdModel. + + Args: + access_list: access_list + comment: comment + pool_name: pool_name + priority: priority + _custom_data: _custom_data + + """ + + class Dynamic(AvdIndexedList[str, DynamicItem]): + """Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`).""" + + _primary_key: ClassVar[str] = "access_list" + + Dynamic._item_type = DynamicItem + + class StaticItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "access_list": {"type": str}, + "comment": {"type": str}, + "direction": {"type": str}, + "group": {"type": int}, + "original_ip": {"type": str}, + "original_port": {"type": int}, + "priority": {"type": int}, + "protocol": {"type": str}, + "translated_ip": {"type": str}, + "translated_port": {"type": int}, + "_custom_data": {"type": dict}, + } + access_list: str | None + """'access_list' and 'group' are mutual exclusive.""" + comment: str | None + direction: Literal["egress", "ingress"] | None + """ + Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware + platform. + EOS might remove this keyword in the configuration. So, check the configuration on + targeted HW/SW. + """ + group: int | None + """'access_list' and 'group' are mutual exclusive.""" + original_ip: str | None + """IPv4 address. The combination of `original_ip` and `original_port` must be unique.""" + original_port: int | None + """TCP/UDP port. The combination of `original_ip` and `original_port` must be unique.""" + priority: int | None + protocol: Literal["udp", "tcp"] | None + translated_ip: str + """IPv4 address.""" + translated_port: int | None + """requires 'original_port'.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + access_list: str | None | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + direction: Literal["egress", "ingress"] | None | UndefinedType = Undefined, + group: int | None | UndefinedType = Undefined, + original_ip: str | None | UndefinedType = Undefined, + original_port: int | None | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + protocol: Literal["udp", "tcp"] | None | UndefinedType = Undefined, + translated_ip: str | UndefinedType = Undefined, + translated_port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StaticItem. + + + Subclass of AvdModel. + + Args: + access_list: 'access_list' and 'group' are mutual exclusive. + comment: comment + direction: + Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware + platform. + EOS might remove this keyword in the configuration. So, check the configuration on + targeted HW/SW. + group: 'access_list' and 'group' are mutual exclusive. + original_ip: IPv4 address. The combination of `original_ip` and `original_port` must be unique. + original_port: TCP/UDP port. The combination of `original_ip` and `original_port` must be unique. + priority: priority + protocol: protocol + translated_ip: IPv4 address. + translated_port: requires 'original_port'. + _custom_data: _custom_data + + """ + + class Static(AvdList[StaticItem]): + """Subclass of AvdList with `StaticItem` items.""" + + Static._item_type = StaticItem + + _fields: ClassVar[dict] = {"dynamic": {"type": Dynamic}, "static": {"type": Static}, "_custom_data": {"type": dict}} + dynamic: Dynamic + """Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`).""" + static: Static + """Subclass of AvdList with `StaticItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dynamic: Dynamic | UndefinedType = Undefined, + static: Static | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Destination. + + + Subclass of AvdModel. + + Args: + dynamic: Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`). + static: Subclass of AvdList with `StaticItem` items. + _custom_data: _custom_data + + """ + + class Source(AvdModel): + """Subclass of AvdModel.""" + + class DynamicItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "access_list": {"type": str}, + "comment": {"type": str}, + "nat_type": {"type": str}, + "pool_name": {"type": str}, + "priority": {"type": int}, + "_custom_data": {"type": dict}, + } + access_list: str + comment: str | None + nat_type: Literal["overload", "pool", "pool-address-only", "pool-full-cone"] + pool_name: str | None + """ + required if 'nat_type' is pool, pool-address-only or pool-full-cone. + ignored if 'nat_type' is + overload. + """ + priority: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + access_list: str | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + nat_type: Literal["overload", "pool", "pool-address-only", "pool-full-cone"] | UndefinedType = Undefined, + pool_name: str | None | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DynamicItem. + + + Subclass of AvdModel. + + Args: + access_list: access_list + comment: comment + nat_type: nat_type + pool_name: + required if 'nat_type' is pool, pool-address-only or pool-full-cone. + ignored if 'nat_type' is + overload. + priority: priority + _custom_data: _custom_data + + """ + + class Dynamic(AvdIndexedList[str, DynamicItem]): + """Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`).""" + + _primary_key: ClassVar[str] = "access_list" + + Dynamic._item_type = DynamicItem + + class StaticItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "access_list": {"type": str}, + "comment": {"type": str}, + "direction": {"type": str}, + "group": {"type": int}, + "original_ip": {"type": str}, + "original_port": {"type": int}, + "priority": {"type": int}, + "protocol": {"type": str}, + "translated_ip": {"type": str}, + "translated_port": {"type": int}, + "_custom_data": {"type": dict}, + } + access_list: str | None + """'access_list' and 'group' are mutual exclusive.""" + comment: str | None + direction: Literal["egress", "ingress"] | None + """ + Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware + platform. + EOS might remove this keyword in the configuration. So, check the configuration on + targeted HW/SW. + """ + group: int | None + """'access_list' and 'group' are mutual exclusive.""" + original_ip: str | None + """IPv4 address. The combination of `original_ip` and `original_port` must be unique.""" + original_port: int | None + """TCP/UDP port. The combination of `original_ip` and `original_port` must be unique.""" + priority: int | None + protocol: Literal["udp", "tcp"] | None + translated_ip: str + """IPv4 address.""" + translated_port: int | None + """requires 'original_port'.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + access_list: str | None | UndefinedType = Undefined, + comment: str | None | UndefinedType = Undefined, + direction: Literal["egress", "ingress"] | None | UndefinedType = Undefined, + group: int | None | UndefinedType = Undefined, + original_ip: str | None | UndefinedType = Undefined, + original_port: int | None | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + protocol: Literal["udp", "tcp"] | None | UndefinedType = Undefined, + translated_ip: str | UndefinedType = Undefined, + translated_port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StaticItem. + + + Subclass of AvdModel. + + Args: + access_list: 'access_list' and 'group' are mutual exclusive. + comment: comment + direction: + Egress or ingress can be the default. This depends on source/destination, EOS version, and hardware + platform. + EOS might remove this keyword in the configuration. So, check the configuration on + targeted HW/SW. + group: 'access_list' and 'group' are mutual exclusive. + original_ip: IPv4 address. The combination of `original_ip` and `original_port` must be unique. + original_port: TCP/UDP port. The combination of `original_ip` and `original_port` must be unique. + priority: priority + protocol: protocol + translated_ip: IPv4 address. + translated_port: requires 'original_port'. + _custom_data: _custom_data + + """ + + class Static(AvdList[StaticItem]): + """Subclass of AvdList with `StaticItem` items.""" + + Static._item_type = StaticItem + + _fields: ClassVar[dict] = {"dynamic": {"type": Dynamic}, "static": {"type": Static}, "_custom_data": {"type": dict}} + dynamic: Dynamic + """Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`).""" + static: Static + """Subclass of AvdList with `StaticItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dynamic: Dynamic | UndefinedType = Undefined, + static: Static | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Source. + + + Subclass of AvdModel. + + Args: + dynamic: Subclass of AvdIndexedList with `DynamicItem` items. Primary key is `access_list` (`str`). + static: Subclass of AvdList with `StaticItem` items. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"destination": {"type": Destination}, "source": {"type": Source}, "_custom_data": {"type": dict}} + destination: Destination + """Subclass of AvdModel.""" + source: Source + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + destination: Destination | UndefinedType = Undefined, + source: Source | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpNat. + + + Subclass of AvdModel. + + Args: + destination: Subclass of AvdModel. + source: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Ipv6AddressVirtuals(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Ipv6AddressVirtuals._item_type = str + + class Ipv6VirtualRouterAddresses(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Ipv6VirtualRouterAddresses._item_type = str + + class Ipv6NdCache(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "dynamic_capacity": {"type": int}, + "expire": {"type": int}, + "refresh_always": {"type": bool}, + "_custom_data": {"type": dict}, + } + dynamic_capacity: int | None + """Capacity of dynamic cache entries.""" + expire: int | None + """Cache entries expirery in seconds.""" + refresh_always: bool | None + """Force refresh on cache expiry.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dynamic_capacity: int | None | UndefinedType = Undefined, + expire: int | None | UndefinedType = Undefined, + refresh_always: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6NdCache. + + + Subclass of AvdModel. + + Args: + dynamic_capacity: Capacity of dynamic cache entries. + expire: Cache entries expirery in seconds. + refresh_always: Force refresh on cache expiry. + _custom_data: _custom_data + + """ + + class Ipv6NdPrefixesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "ipv6_prefix": {"type": str}, + "valid_lifetime": {"type": str}, + "preferred_lifetime": {"type": str}, + "no_autoconfig_flag": {"type": bool}, + "_custom_data": {"type": dict}, + } + ipv6_prefix: str + """IPv6_address/Mask.""" + valid_lifetime: str | None + """In seconds <0-4294967295> or infinite.""" + preferred_lifetime: str | None + """In seconds <0-4294967295> or infinite.""" + no_autoconfig_flag: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv6_prefix: str | UndefinedType = Undefined, + valid_lifetime: str | None | UndefinedType = Undefined, + preferred_lifetime: str | None | UndefinedType = Undefined, + no_autoconfig_flag: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6NdPrefixesItem. + + + Subclass of AvdModel. + + Args: + ipv6_prefix: IPv6_address/Mask. + valid_lifetime: In seconds <0-4294967295> or infinite. + preferred_lifetime: In seconds <0-4294967295> or infinite. + no_autoconfig_flag: no_autoconfig_flag + _custom_data: _custom_data + + """ + + class Ipv6NdPrefixes(AvdIndexedList[str, Ipv6NdPrefixesItem]): + """Subclass of AvdIndexedList with `Ipv6NdPrefixesItem` items. Primary key is `ipv6_prefix` (`str`).""" + + _primary_key: ClassVar[str] = "ipv6_prefix" + + Ipv6NdPrefixes._item_type = Ipv6NdPrefixesItem + + class Ipv6DhcpRelayDestinationsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "address": {"type": str}, + "vrf": {"type": str}, + "local_interface": {"type": str}, + "source_address": {"type": str}, + "link_address": {"type": str}, + "_custom_data": {"type": dict}, + } + address: str + """DHCP server's IPv6 address.""" + vrf: str | None + local_interface: str | None + """Local interface to communicate with DHCP server - mutually exclusive to source_address.""" + source_address: str | None + """Source IPv6 address to communicate with DHCP server - mutually exclusive to local_interface.""" + link_address: str | None + """Override the default link address specified in the relayed DHCP packet.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + address: str | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + local_interface: str | None | UndefinedType = Undefined, + source_address: str | None | UndefinedType = Undefined, + link_address: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6DhcpRelayDestinationsItem. + + + Subclass of AvdModel. + + Args: + address: DHCP server's IPv6 address. + vrf: vrf + local_interface: Local interface to communicate with DHCP server - mutually exclusive to source_address. + source_address: Source IPv6 address to communicate with DHCP server - mutually exclusive to local_interface. + link_address: Override the default link address specified in the relayed DHCP packet. + _custom_data: _custom_data + + """ + + class Ipv6DhcpRelayDestinations(AvdIndexedList[str, Ipv6DhcpRelayDestinationsItem]): + """ + Subclass of AvdIndexedList with `Ipv6DhcpRelayDestinationsItem` items. Primary key is `address` + (`str`). + """ + + _primary_key: ClassVar[str] = "address" + + Ipv6DhcpRelayDestinations._item_type = Ipv6DhcpRelayDestinationsItem + + class Multicast(AvdModel): + """Subclass of AvdModel.""" + + class Ipv4(AvdModel): + """Subclass of AvdModel.""" + + class BoundariesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"boundary": {"type": str}, "out": {"type": bool}, "_custom_data": {"type": dict}} + boundary: str + """IPv4 access-list name or IPv4 multicast group prefix with mask.""" + out: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + boundary: str | UndefinedType = Undefined, + out: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BoundariesItem. + + + Subclass of AvdModel. + + Args: + boundary: IPv4 access-list name or IPv4 multicast group prefix with mask. + out: out + _custom_data: _custom_data + + """ + + class Boundaries(AvdIndexedList[str, BoundariesItem]): + """Subclass of AvdIndexedList with `BoundariesItem` items. Primary key is `boundary` (`str`).""" + + _primary_key: ClassVar[str] = "boundary" + + Boundaries._item_type = BoundariesItem + + class SourceRouteExport(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "administrative_distance": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool + administrative_distance: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + administrative_distance: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SourceRouteExport. + + + Subclass of AvdModel. + + Args: + enabled: enabled + administrative_distance: administrative_distance + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "boundaries": {"type": Boundaries}, + "source_route_export": {"type": SourceRouteExport}, + "static": {"type": bool}, + "_custom_data": {"type": dict}, + } + boundaries: Boundaries + """ + Boundaries can be either 1 ACL or a list of multicast IP address_range(s)/prefix but not combination + of both. + + Subclass of AvdIndexedList with `BoundariesItem` items. Primary key is `boundary` (`str`). + """ + source_route_export: SourceRouteExport + """Subclass of AvdModel.""" + static: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + boundaries: Boundaries | UndefinedType = Undefined, + source_route_export: SourceRouteExport | UndefinedType = Undefined, + static: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4. + + + Subclass of AvdModel. + + Args: + boundaries: + Boundaries can be either 1 ACL or a list of multicast IP address_range(s)/prefix but not combination + of both. + + Subclass of AvdIndexedList with `BoundariesItem` items. Primary key is `boundary` (`str`). + source_route_export: Subclass of AvdModel. + static: static + _custom_data: _custom_data + + """ + + class Ipv6(AvdModel): + """Subclass of AvdModel.""" + + class BoundariesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"boundary": {"type": str}, "_custom_data": {"type": dict}} + boundary: str + """IPv6 access-list name or IPv6 multicast group prefix with mask.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, boundary: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + BoundariesItem. + + + Subclass of AvdModel. + + Args: + boundary: IPv6 access-list name or IPv6 multicast group prefix with mask. + _custom_data: _custom_data + + """ + + class Boundaries(AvdIndexedList[str, BoundariesItem]): + """Subclass of AvdIndexedList with `BoundariesItem` items. Primary key is `boundary` (`str`).""" + + _primary_key: ClassVar[str] = "boundary" + + Boundaries._item_type = BoundariesItem + + class SourceRouteExport(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "administrative_distance": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool + administrative_distance: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + administrative_distance: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SourceRouteExport. + + + Subclass of AvdModel. + + Args: + enabled: enabled + administrative_distance: administrative_distance + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "boundaries": {"type": Boundaries}, + "source_route_export": {"type": SourceRouteExport}, + "static": {"type": bool}, + "_custom_data": {"type": dict}, + } + boundaries: Boundaries + """ + Boundaries can be either 1 ACL or a list of multicast IP address_range(s)/prefix but not combination + of both. + + Subclass of AvdIndexedList with `BoundariesItem` items. Primary key is `boundary` (`str`). + """ + source_route_export: SourceRouteExport + """Subclass of AvdModel.""" + static: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + boundaries: Boundaries | UndefinedType = Undefined, + source_route_export: SourceRouteExport | UndefinedType = Undefined, + static: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6. + + + Subclass of AvdModel. + + Args: + boundaries: + Boundaries can be either 1 ACL or a list of multicast IP address_range(s)/prefix but not combination + of both. + + Subclass of AvdIndexedList with `BoundariesItem` items. Primary key is `boundary` (`str`). + source_route_export: Subclass of AvdModel. + static: static + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ipv4": {"type": Ipv4}, "ipv6": {"type": Ipv6}, "_custom_data": {"type": dict}} + ipv4: Ipv4 + """Subclass of AvdModel.""" + ipv6: Ipv6 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4: Ipv4 | UndefinedType = Undefined, + ipv6: Ipv6 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Multicast. + + + Subclass of AvdModel. + + Args: + ipv4: Subclass of AvdModel. + ipv6: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class OspfMessageDigestKeysItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"id": {"type": int}, "hash_algorithm": {"type": str}, "key": {"type": str}, "_custom_data": {"type": dict}} + id: int + hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None + key: str | None + """Encrypted password.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + OspfMessageDigestKeysItem. + + + Subclass of AvdModel. + + Args: + id: id + hash_algorithm: hash_algorithm + key: Encrypted password. + _custom_data: _custom_data + + """ + + class OspfMessageDigestKeys(AvdIndexedList[int, OspfMessageDigestKeysItem]): + """Subclass of AvdIndexedList with `OspfMessageDigestKeysItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + OspfMessageDigestKeys._item_type = OspfMessageDigestKeysItem + + class Pim(AvdModel): + """Subclass of AvdModel.""" + + class Ipv4(AvdModel): + """Subclass of AvdModel.""" + + class Hello(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"count": {"type": str}, "interval": {"type": int}, "_custom_data": {"type": dict}} + count: str | None + """Number of missed hellos after which the neighbor expires. Range <1.5-65535>.""" + interval: int | None + """PIM hello interval in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + count: str | None | UndefinedType = Undefined, + interval: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Hello. + + + Subclass of AvdModel. + + Args: + count: Number of missed hellos after which the neighbor expires. Range <1.5-65535>. + interval: PIM hello interval in seconds. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "border_router": {"type": bool}, + "dr_priority": {"type": int}, + "sparse_mode": {"type": bool}, + "local_interface": {"type": str}, + "bfd": {"type": bool}, + "bidirectional": {"type": bool}, + "hello": {"type": Hello}, + "_custom_data": {"type": dict}, + } + border_router: bool | None + """Configure PIM border router. EOS default is false.""" + dr_priority: int | None + sparse_mode: bool | None + local_interface: str | None + bfd: bool | None + """Set the default for whether Bidirectional Forwarding Detection is enabled for PIM.""" + bidirectional: bool | None + hello: Hello + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + border_router: bool | None | UndefinedType = Undefined, + dr_priority: int | None | UndefinedType = Undefined, + sparse_mode: bool | None | UndefinedType = Undefined, + local_interface: str | None | UndefinedType = Undefined, + bfd: bool | None | UndefinedType = Undefined, + bidirectional: bool | None | UndefinedType = Undefined, + hello: Hello | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4. + + + Subclass of AvdModel. + + Args: + border_router: Configure PIM border router. EOS default is false. + dr_priority: dr_priority + sparse_mode: sparse_mode + local_interface: local_interface + bfd: Set the default for whether Bidirectional Forwarding Detection is enabled for PIM. + bidirectional: bidirectional + hello: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"ipv4": {"type": Ipv4}, "_custom_data": {"type": dict}} + ipv4: Ipv4 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, ipv4: Ipv4 | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Pim. + + + Subclass of AvdModel. + + Args: + ipv4: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class IsisAuthentication(AvdModel): + """Subclass of AvdModel.""" + + class Both(AvdModel): + """Subclass of AvdModel.""" + + class KeyIdsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "algorithm": {"type": str}, + "key_type": {"type": str}, + "key": {"type": str}, + "rfc_5310": {"type": bool}, + "_custom_data": {"type": dict}, + } + id: int + """Configure authentication key-id.""" + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + key_type: Literal["0", "7", "8a"] + """Configure authentication key type.""" + key: str + """Password string.""" + rfc_5310: bool | None + """SHA digest computation according to rfc5310.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + key_type: Literal["0", "7", "8a"] | UndefinedType = Undefined, + key: str | UndefinedType = Undefined, + rfc_5310: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + KeyIdsItem. + + + Subclass of AvdModel. + + Args: + id: Configure authentication key-id. + algorithm: algorithm + key_type: Configure authentication key type. + key: Password string. + rfc_5310: SHA digest computation according to rfc5310. + _custom_data: _custom_data + + """ + + class KeyIds(AvdIndexedList[int, KeyIdsItem]): + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + KeyIds._item_type = KeyIdsItem + + class Sha(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"key_id": {"type": int}, "_custom_data": {"type": dict}} + key_id: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, key_id: int | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Sha. + + + Subclass of AvdModel. + + Args: + key_id: key_id + _custom_data: _custom_data + + """ + + class SharedSecret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "algorithm": {"type": str}, "_custom_data": {"type": dict}} + profile: str + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SharedSecret. + + + Subclass of AvdModel. + + Args: + profile: profile + algorithm: algorithm + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "key_type": {"type": str}, + "key": {"type": str}, + "key_ids": {"type": KeyIds}, + "mode": {"type": str}, + "sha": {"type": Sha}, + "shared_secret": {"type": SharedSecret}, + "rx_disabled": {"type": bool}, + "_custom_data": {"type": dict}, + } + key_type: Literal["0", "7", "8a"] | None + """Configure authentication key type.""" + key: str | None + """Password string. `key_type` is required for this setting.""" + key_ids: KeyIds + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + mode: Literal["md5", "sha", "text", "shared-secret"] | None + """Authentication mode.""" + sha: Sha + """ + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + """ + shared_secret: SharedSecret + """ + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + """ + rx_disabled: bool | None + """Disable authentication check on the receive side.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + key_type: Literal["0", "7", "8a"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + key_ids: KeyIds | UndefinedType = Undefined, + mode: Literal["md5", "sha", "text", "shared-secret"] | None | UndefinedType = Undefined, + sha: Sha | UndefinedType = Undefined, + shared_secret: SharedSecret | UndefinedType = Undefined, + rx_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Both. + + + Subclass of AvdModel. + + Args: + key_type: Configure authentication key type. + key: Password string. `key_type` is required for this setting. + key_ids: Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`). + mode: Authentication mode. + sha: + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + shared_secret: + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + rx_disabled: Disable authentication check on the receive side. + _custom_data: _custom_data + + """ + + class Level1(AvdModel): + """Subclass of AvdModel.""" + + class KeyIdsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "algorithm": {"type": str}, + "key_type": {"type": str}, + "key": {"type": str}, + "rfc_5310": {"type": bool}, + "_custom_data": {"type": dict}, + } + id: int + """Configure authentication key-id.""" + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + key_type: Literal["0", "7", "8a"] + """Configure authentication key type.""" + key: str + """Password string.""" + rfc_5310: bool | None + """SHA digest computation according to rfc5310.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + key_type: Literal["0", "7", "8a"] | UndefinedType = Undefined, + key: str | UndefinedType = Undefined, + rfc_5310: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + KeyIdsItem. + + + Subclass of AvdModel. + + Args: + id: Configure authentication key-id. + algorithm: algorithm + key_type: Configure authentication key type. + key: Password string. + rfc_5310: SHA digest computation according to rfc5310. + _custom_data: _custom_data + + """ + + class KeyIds(AvdIndexedList[int, KeyIdsItem]): + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + KeyIds._item_type = KeyIdsItem + + class Sha(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"key_id": {"type": int}, "_custom_data": {"type": dict}} + key_id: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, key_id: int | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Sha. + + + Subclass of AvdModel. + + Args: + key_id: key_id + _custom_data: _custom_data + + """ + + class SharedSecret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "algorithm": {"type": str}, "_custom_data": {"type": dict}} + profile: str + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SharedSecret. + + + Subclass of AvdModel. + + Args: + profile: profile + algorithm: algorithm + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "key_type": {"type": str}, + "key": {"type": str}, + "key_ids": {"type": KeyIds}, + "mode": {"type": str}, + "sha": {"type": Sha}, + "shared_secret": {"type": SharedSecret}, + "rx_disabled": {"type": bool}, + "_custom_data": {"type": dict}, + } + key_type: Literal["0", "7", "8a"] | None + """Configure authentication key type.""" + key: str | None + """Password string. `key_type` is required for this setting.""" + key_ids: KeyIds + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + mode: Literal["md5", "sha", "text", "shared-secret"] | None + """Authentication mode.""" + sha: Sha + """ + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + """ + shared_secret: SharedSecret + """ + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + """ + rx_disabled: bool | None + """Disable authentication check on the receive side.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + key_type: Literal["0", "7", "8a"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + key_ids: KeyIds | UndefinedType = Undefined, + mode: Literal["md5", "sha", "text", "shared-secret"] | None | UndefinedType = Undefined, + sha: Sha | UndefinedType = Undefined, + shared_secret: SharedSecret | UndefinedType = Undefined, + rx_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Level1. + + + Subclass of AvdModel. + + Args: + key_type: Configure authentication key type. + key: Password string. `key_type` is required for this setting. + key_ids: Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`). + mode: Authentication mode. + sha: + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + shared_secret: + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + rx_disabled: Disable authentication check on the receive side. + _custom_data: _custom_data + + """ + + class Level2(AvdModel): + """Subclass of AvdModel.""" + + class KeyIdsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "algorithm": {"type": str}, + "key_type": {"type": str}, + "key": {"type": str}, + "rfc_5310": {"type": bool}, + "_custom_data": {"type": dict}, + } + id: int + """Configure authentication key-id.""" + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + key_type: Literal["0", "7", "8a"] + """Configure authentication key type.""" + key: str + """Password string.""" + rfc_5310: bool | None + """SHA digest computation according to rfc5310.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + algorithm: Literal["sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + key_type: Literal["0", "7", "8a"] | UndefinedType = Undefined, + key: str | UndefinedType = Undefined, + rfc_5310: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + KeyIdsItem. + + + Subclass of AvdModel. + + Args: + id: Configure authentication key-id. + algorithm: algorithm + key_type: Configure authentication key type. + key: Password string. + rfc_5310: SHA digest computation according to rfc5310. + _custom_data: _custom_data + + """ + + class KeyIds(AvdIndexedList[int, KeyIdsItem]): + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + KeyIds._item_type = KeyIdsItem + + class Sha(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"key_id": {"type": int}, "_custom_data": {"type": dict}} + key_id: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, key_id: int | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Sha. + + + Subclass of AvdModel. + + Args: + key_id: key_id + _custom_data: _custom_data + + """ + + class SharedSecret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "algorithm": {"type": str}, "_custom_data": {"type": dict}} + profile: str + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + algorithm: Literal["md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SharedSecret. + + + Subclass of AvdModel. + + Args: + profile: profile + algorithm: algorithm + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "key_type": {"type": str}, + "key": {"type": str}, + "key_ids": {"type": KeyIds}, + "mode": {"type": str}, + "sha": {"type": Sha}, + "shared_secret": {"type": SharedSecret}, + "rx_disabled": {"type": bool}, + "_custom_data": {"type": dict}, + } + key_type: Literal["0", "7", "8a"] | None + """Configure authentication key type.""" + key: str | None + """Password string. `key_type` is required for this setting.""" + key_ids: KeyIds + """Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`).""" + mode: Literal["md5", "sha", "text", "shared-secret"] | None + """Authentication mode.""" + sha: Sha + """ + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + """ + shared_secret: SharedSecret + """ + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + """ + rx_disabled: bool | None + """Disable authentication check on the receive side.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + key_type: Literal["0", "7", "8a"] | None | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + key_ids: KeyIds | UndefinedType = Undefined, + mode: Literal["md5", "sha", "text", "shared-secret"] | None | UndefinedType = Undefined, + sha: Sha | UndefinedType = Undefined, + shared_secret: SharedSecret | UndefinedType = Undefined, + rx_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Level2. + + + Subclass of AvdModel. + + Args: + key_type: Configure authentication key type. + key: Password string. `key_type` is required for this setting. + key_ids: Subclass of AvdIndexedList with `KeyIdsItem` items. Primary key is `id` (`int`). + mode: Authentication mode. + sha: + Required settings for authentication mode 'sha'. + + Subclass of AvdModel. + shared_secret: + Required settings for authentication mode 'shared_secret'. + + Subclass of AvdModel. + rx_disabled: Disable authentication check on the receive side. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"both": {"type": Both}, "level_1": {"type": Level1}, "level_2": {"type": Level2}, "_custom_data": {"type": dict}} + both: Both + """ + Authentication settings for level-1 and level-2. 'both' takes precedence over 'level_1' and + 'level_2' settings. + + Subclass of AvdModel. + """ + level_1: Level1 + """ + Authentication settings for level-1. 'both' takes precedence over 'level_1' and 'level_2' settings. + Subclass of AvdModel. + """ + level_2: Level2 + """ + Authentication settings for level-2. 'both' takes precedence over 'level_1' and 'level_2' settings. + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + both: Both | UndefinedType = Undefined, + level_1: Level1 | UndefinedType = Undefined, + level_2: Level2 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IsisAuthentication. + + + Subclass of AvdModel. + + Args: + both: + Authentication settings for level-1 and level-2. 'both' takes precedence over 'level_1' and + 'level_2' settings. + + Subclass of AvdModel. + level_1: + Authentication settings for level-1. 'both' takes precedence over 'level_1' and 'level_2' settings. + Subclass of AvdModel. + level_2: + Authentication settings for level-2. 'both' takes precedence over 'level_1' and 'level_2' settings. + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class VrrpIdsItem(AvdModel): + """Subclass of AvdModel.""" + + class Advertisement(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interval": {"type": int}, "_custom_data": {"type": dict}} + interval: int | None + """Interval in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, interval: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Advertisement. + + + Subclass of AvdModel. + + Args: + interval: Interval in seconds. + _custom_data: _custom_data + + """ + + class Preempt(AvdModel): + """Subclass of AvdModel.""" + + class Delay(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"minimum": {"type": int}, "reload": {"type": int}, "_custom_data": {"type": dict}} + minimum: int | None + """Minimum preempt delay in seconds.""" + reload: int | None + """Reload preempt delay in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + minimum: int | None | UndefinedType = Undefined, + reload: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Delay. + + + Subclass of AvdModel. + + Args: + minimum: Minimum preempt delay in seconds. + reload: Reload preempt delay in seconds. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "delay": {"type": Delay}, "_custom_data": {"type": dict}} + enabled: bool + delay: Delay + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + delay: Delay | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Preempt. + + + Subclass of AvdModel. + + Args: + enabled: enabled + delay: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Timers(AvdModel): + """Subclass of AvdModel.""" + + class Delay(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"reload": {"type": int}, "_custom_data": {"type": dict}} + reload: int | None + """Delay after reload in seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, reload: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Delay. + + + Subclass of AvdModel. + + Args: + reload: Delay after reload in seconds. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"delay": {"type": Delay}, "_custom_data": {"type": dict}} + delay: Delay + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, delay: Delay | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Timers. + + + Subclass of AvdModel. + + Args: + delay: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class TrackedObjectItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "decrement": {"type": int}, "shutdown": {"type": bool}, "_custom_data": {"type": dict}} + name: str + """Tracked object name.""" + decrement: int | None + """Decrement VRRP priority by 1-254.""" + shutdown: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + decrement: int | None | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TrackedObjectItem. + + + Subclass of AvdModel. + + Args: + name: Tracked object name. + decrement: Decrement VRRP priority by 1-254. + shutdown: shutdown + _custom_data: _custom_data + + """ + + class TrackedObject(AvdIndexedList[str, TrackedObjectItem]): + """Subclass of AvdIndexedList with `TrackedObjectItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + TrackedObject._item_type = TrackedObjectItem + + class Ipv4(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"address": {"type": str}, "version": {"type": int}, "_custom_data": {"type": dict}} + address: str + """Virtual IPv4 address.""" + version: Literal[2, 3] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + address: str | UndefinedType = Undefined, + version: Literal[2, 3] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4. + + + Subclass of AvdModel. + + Args: + address: Virtual IPv4 address. + version: version + _custom_data: _custom_data + + """ + + class Ipv6(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"address": {"type": str}, "_custom_data": {"type": dict}} + address: str + """Virtual IPv6 address.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, address: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Ipv6. + + + Subclass of AvdModel. + + Args: + address: Virtual IPv6 address. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "priority_level": {"type": int}, + "advertisement": {"type": Advertisement}, + "preempt": {"type": Preempt}, + "timers": {"type": Timers}, + "tracked_object": {"type": TrackedObject}, + "ipv4": {"type": Ipv4}, + "ipv6": {"type": Ipv6}, + "_custom_data": {"type": dict}, + } + id: int + """VRID.""" + priority_level: int | None + """Instance priority.""" + advertisement: Advertisement + """Subclass of AvdModel.""" + preempt: Preempt + """Subclass of AvdModel.""" + timers: Timers + """Subclass of AvdModel.""" + tracked_object: TrackedObject + """Subclass of AvdIndexedList with `TrackedObjectItem` items. Primary key is `name` (`str`).""" + ipv4: Ipv4 + """Subclass of AvdModel.""" + ipv6: Ipv6 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + priority_level: int | None | UndefinedType = Undefined, + advertisement: Advertisement | UndefinedType = Undefined, + preempt: Preempt | UndefinedType = Undefined, + timers: Timers | UndefinedType = Undefined, + tracked_object: TrackedObject | UndefinedType = Undefined, + ipv4: Ipv4 | UndefinedType = Undefined, + ipv6: Ipv6 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrrpIdsItem. + + + Subclass of AvdModel. + + Args: + id: VRID. + priority_level: Instance priority. + advertisement: Subclass of AvdModel. + preempt: Subclass of AvdModel. + timers: Subclass of AvdModel. + tracked_object: Subclass of AvdIndexedList with `TrackedObjectItem` items. Primary key is `name` (`str`). + ipv4: Subclass of AvdModel. + ipv6: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class VrrpIds(AvdIndexedList[int, VrrpIdsItem]): + """Subclass of AvdIndexedList with `VrrpIdsItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + VrrpIds._item_type = VrrpIdsItem + + class IpAttachedHostRouteExport(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "distance": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool + distance: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + distance: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpAttachedHostRouteExport. + + + Subclass of AvdModel. + + Args: + enabled: enabled + distance: distance + _custom_data: _custom_data + + """ + + class Ipv6AttachedHostRouteExport(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "distance": {"type": int}, "prefix_length": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool + distance: int | None + """Administrative distance for generated routes.""" + prefix_length: int | None + """Prefix length for generated routes.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + distance: int | None | UndefinedType = Undefined, + prefix_length: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6AttachedHostRouteExport. + + + Subclass of AvdModel. + + Args: + enabled: enabled + distance: Administrative distance for generated routes. + prefix_length: Prefix length for generated routes. + _custom_data: _custom_data + + """ + + class Bfd(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "echo": {"type": bool}, + "interval": {"type": int}, + "min_rx": {"type": int}, + "multiplier": {"type": int}, + "_custom_data": {"type": dict}, + } + echo: bool | None + interval: int | None + """Rate in milliseconds.""" + min_rx: int | None + """Minimum RX hold time in milliseconds.""" + multiplier: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + echo: bool | None | UndefinedType = Undefined, + interval: int | None | UndefinedType = Undefined, + min_rx: int | None | UndefinedType = Undefined, + multiplier: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bfd. + + + Subclass of AvdModel. + + Args: + echo: echo + interval: Rate in milliseconds. + min_rx: Minimum RX hold time in milliseconds. + multiplier: multiplier + _custom_data: _custom_data + + """ + + class ServicePolicy(AvdModel): + """Subclass of AvdModel.""" + + class Pbr(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"input": {"type": str}, "_custom_data": {"type": dict}} + input: str | None + """Name of policy-map used for policy based routing.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, input: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Pbr. + + + Subclass of AvdModel. + + Args: + input: Name of policy-map used for policy based routing. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"pbr": {"type": Pbr}, "_custom_data": {"type": dict}} + pbr: Pbr + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, pbr: Pbr | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + ServicePolicy. + + + Subclass of AvdModel. + + Args: + pbr: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Tags(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tags._item_type = str + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "description": {"type": str}, + "logging": {"type": Logging}, + "shutdown": {"type": bool}, + "vrf": {"type": str}, + "arp_aging_timeout": {"type": int}, + "arp_cache_dynamic_capacity": {"type": int}, + "arp_gratuitous_accept": {"type": bool}, + "arp_monitor_mac_address": {"type": bool}, + "ip_proxy_arp": {"type": bool}, + "ip_directed_broadcast": {"type": bool}, + "ip_address": {"type": str}, + "ip_address_secondaries": {"type": IpAddressSecondaries}, + "ip_virtual_router_addresses": {"type": IpVirtualRouterAddresses}, + "ip_address_virtual": {"type": str}, + "ip_address_virtual_secondaries": {"type": IpAddressVirtualSecondaries}, + "ip_verify_unicast_source_reachable_via": {"type": str}, + "ip_igmp": {"type": bool}, + "ip_igmp_version": {"type": int}, + "ip_igmp_host_proxy": {"type": IpIgmpHostProxy}, + "ip_helpers": {"type": IpHelpers}, + "ip_dhcp_relay_all_subnets": {"type": bool}, + "ip_nat": {"type": IpNat}, + "ipv6_enable": {"type": bool}, + "ipv6_address": {"type": str}, + "ipv6_address_virtuals": {"type": Ipv6AddressVirtuals}, + "ipv6_address_link_local": {"type": str}, + "ipv6_virtual_router_addresses": {"type": Ipv6VirtualRouterAddresses}, + "ipv6_nd_ra_disabled": {"type": bool}, + "ipv6_nd_managed_config_flag": {"type": bool}, + "ipv6_nd_other_config_flag": {"type": bool}, + "ipv6_nd_cache": {"type": Ipv6NdCache}, + "ipv6_nd_prefixes": {"type": Ipv6NdPrefixes}, + "ipv6_dhcp_relay_destinations": {"type": Ipv6DhcpRelayDestinations}, + "ipv6_dhcp_relay_all_subnets": {"type": bool}, + "access_group_in": {"type": str}, + "access_group_out": {"type": str}, + "ipv6_access_group_in": {"type": str}, + "ipv6_access_group_out": {"type": str}, + "multicast": {"type": Multicast}, + "ospf_network_point_to_point": {"type": bool}, + "ospf_area": {"type": str}, + "ospf_cost": {"type": int}, + "ospf_authentication": {"type": str}, + "ospf_authentication_key": {"type": str}, + "ospf_message_digest_keys": {"type": OspfMessageDigestKeys}, + "pim": {"type": Pim}, + "isis_enable": {"type": str}, + "isis_bfd": {"type": bool}, + "isis_passive": {"type": bool}, + "isis_metric": {"type": int}, + "isis_network_point_to_point": {"type": bool}, + "isis_authentication": {"type": IsisAuthentication}, + "mtu": {"type": int}, + "no_autostate": {"type": bool}, + "vrrp_ids": {"type": VrrpIds}, + "ip_attached_host_route_export": {"type": IpAttachedHostRouteExport}, + "ipv6_attached_host_route_export": {"type": Ipv6AttachedHostRouteExport}, + "bfd": {"type": Bfd}, + "service_policy": {"type": ServicePolicy}, + "pvlan_mapping": {"type": str}, + "tenant": {"type": str}, + "tags": {"type": Tags}, + "type": {"type": str}, + "eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """VLAN interface name like "Vlan123".""" + description: str | None + logging: Logging + """Subclass of AvdModel.""" + shutdown: bool | None + vrf: str | None + """VRF name.""" + arp_aging_timeout: int | None + """In seconds.""" + arp_cache_dynamic_capacity: int | None + arp_gratuitous_accept: bool | None + arp_monitor_mac_address: bool | None + ip_proxy_arp: bool | None + ip_directed_broadcast: bool | None + ip_address: str | None + """IPv4_address/Mask.""" + ip_address_secondaries: IpAddressSecondaries + """Subclass of AvdList with `str` items.""" + ip_virtual_router_addresses: IpVirtualRouterAddresses + """Subclass of AvdList with `str` items.""" + ip_address_virtual: str | None + """IPv4_address/Mask.""" + ip_address_virtual_secondaries: IpAddressVirtualSecondaries + """Subclass of AvdList with `str` items.""" + ip_verify_unicast_source_reachable_via: Literal["any", "rx"] | None + ip_igmp: bool | None + ip_igmp_version: int | None + ip_igmp_host_proxy: IpIgmpHostProxy + """Subclass of AvdModel.""" + ip_helpers: IpHelpers + """ + List of DHCP servers. + + Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is + `ip_helper` (`str`). + """ + ip_dhcp_relay_all_subnets: bool | None + """Allow forwarding requests with secondary IP addresses in the gateway address "giaddr" field.""" + ip_nat: IpNat + """Subclass of AvdModel.""" + ipv6_enable: bool | None + ipv6_address: str | None + """IPv6_address/Mask.""" + ipv6_address_virtuals: Ipv6AddressVirtuals + """ + The new "ipv6_address_virtuals" key support multiple virtual ipv6 addresses. + + Subclass of AvdList + with `str` items. + """ + ipv6_address_link_local: str | None + """IPv6_address/Mask.""" + ipv6_virtual_router_addresses: Ipv6VirtualRouterAddresses + """ + Improved "VARPv6" data model to support multiple VARPv6 addresses. + + Subclass of AvdList with `str` + items. + """ + ipv6_nd_ra_disabled: bool | None + ipv6_nd_managed_config_flag: bool | None + ipv6_nd_other_config_flag: bool | None + """Set the "other stateful configuration" flag in IPv6 router advertisements.""" + ipv6_nd_cache: Ipv6NdCache + """ + IPv6 neighbor cache options. + + Subclass of AvdModel. + """ + ipv6_nd_prefixes: Ipv6NdPrefixes + """Subclass of AvdIndexedList with `Ipv6NdPrefixesItem` items. Primary key is `ipv6_prefix` (`str`).""" + ipv6_dhcp_relay_destinations: Ipv6DhcpRelayDestinations + """ + Subclass of AvdIndexedList with `Ipv6DhcpRelayDestinationsItem` items. Primary key is `address` + (`str`). + """ + ipv6_dhcp_relay_all_subnets: bool | None + """Allow forwarding requests with additional IPv6 addresses in the gateway address "giaddr" field.""" + access_group_in: str | None + """IPv4 access-list name.""" + access_group_out: str | None + """IPv4 access-list name.""" + ipv6_access_group_in: str | None + """IPv6 access-list name.""" + ipv6_access_group_out: str | None + """IPv6 access-list name.""" + multicast: Multicast + """Subclass of AvdModel.""" + ospf_network_point_to_point: bool | None + ospf_area: str | None + ospf_cost: int | None + ospf_authentication: Literal["none", "simple", "message-digest"] | None + ospf_authentication_key: str | None + """Encrypted password used for simple authentication.""" + ospf_message_digest_keys: OspfMessageDigestKeys + """ + Keys used for message-digest authentication. + + Subclass of AvdIndexedList with + `OspfMessageDigestKeysItem` items. Primary key is `id` (`int`). + """ + pim: Pim + """Subclass of AvdModel.""" + isis_enable: str | None + """ISIS instance name.""" + isis_bfd: bool | None + """Enable BFD for ISIS.""" + isis_passive: bool | None + isis_metric: int | None + isis_network_point_to_point: bool | None + isis_authentication: IsisAuthentication + """Subclass of AvdModel.""" + mtu: int | None + no_autostate: bool | None + vrrp_ids: VrrpIds + """ + Improved "vrrp" data model to support multiple VRRP IDs. + + Subclass of AvdIndexedList with + `VrrpIdsItem` items. Primary key is `id` (`int`). + """ + ip_attached_host_route_export: IpAttachedHostRouteExport + """Subclass of AvdModel.""" + ipv6_attached_host_route_export: Ipv6AttachedHostRouteExport + """Subclass of AvdModel.""" + bfd: Bfd + """Subclass of AvdModel.""" + service_policy: ServicePolicy + """Subclass of AvdModel.""" + pvlan_mapping: str | None + """List of VLANs as string.""" + tenant: str | None + """Key only used for documentation or validation purposes.""" + tags: Tags + """ + Key only used for documentation or validation purposes. + + Subclass of AvdList with `str` items. + """ + type: str | None + """Key only used for documentation or validation purposes.""" + eos_cli: str | None + """Multiline EOS CLI rendered directly on the VLAN interface in the final EOS configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + logging: Logging | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + arp_aging_timeout: int | None | UndefinedType = Undefined, + arp_cache_dynamic_capacity: int | None | UndefinedType = Undefined, + arp_gratuitous_accept: bool | None | UndefinedType = Undefined, + arp_monitor_mac_address: bool | None | UndefinedType = Undefined, + ip_proxy_arp: bool | None | UndefinedType = Undefined, + ip_directed_broadcast: bool | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + ip_address_secondaries: IpAddressSecondaries | UndefinedType = Undefined, + ip_virtual_router_addresses: IpVirtualRouterAddresses | UndefinedType = Undefined, + ip_address_virtual: str | None | UndefinedType = Undefined, + ip_address_virtual_secondaries: IpAddressVirtualSecondaries | UndefinedType = Undefined, + ip_verify_unicast_source_reachable_via: Literal["any", "rx"] | None | UndefinedType = Undefined, + ip_igmp: bool | None | UndefinedType = Undefined, + ip_igmp_version: int | None | UndefinedType = Undefined, + ip_igmp_host_proxy: IpIgmpHostProxy | UndefinedType = Undefined, + ip_helpers: IpHelpers | UndefinedType = Undefined, + ip_dhcp_relay_all_subnets: bool | None | UndefinedType = Undefined, + ip_nat: IpNat | UndefinedType = Undefined, + ipv6_enable: bool | None | UndefinedType = Undefined, + ipv6_address: str | None | UndefinedType = Undefined, + ipv6_address_virtuals: Ipv6AddressVirtuals | UndefinedType = Undefined, + ipv6_address_link_local: str | None | UndefinedType = Undefined, + ipv6_virtual_router_addresses: Ipv6VirtualRouterAddresses | UndefinedType = Undefined, + ipv6_nd_ra_disabled: bool | None | UndefinedType = Undefined, + ipv6_nd_managed_config_flag: bool | None | UndefinedType = Undefined, + ipv6_nd_other_config_flag: bool | None | UndefinedType = Undefined, + ipv6_nd_cache: Ipv6NdCache | UndefinedType = Undefined, + ipv6_nd_prefixes: Ipv6NdPrefixes | UndefinedType = Undefined, + ipv6_dhcp_relay_destinations: Ipv6DhcpRelayDestinations | UndefinedType = Undefined, + ipv6_dhcp_relay_all_subnets: bool | None | UndefinedType = Undefined, + access_group_in: str | None | UndefinedType = Undefined, + access_group_out: str | None | UndefinedType = Undefined, + ipv6_access_group_in: str | None | UndefinedType = Undefined, + ipv6_access_group_out: str | None | UndefinedType = Undefined, + multicast: Multicast | UndefinedType = Undefined, + ospf_network_point_to_point: bool | None | UndefinedType = Undefined, + ospf_area: str | None | UndefinedType = Undefined, + ospf_cost: int | None | UndefinedType = Undefined, + ospf_authentication: Literal["none", "simple", "message-digest"] | None | UndefinedType = Undefined, + ospf_authentication_key: str | None | UndefinedType = Undefined, + ospf_message_digest_keys: OspfMessageDigestKeys | UndefinedType = Undefined, + pim: Pim | UndefinedType = Undefined, + isis_enable: str | None | UndefinedType = Undefined, + isis_bfd: bool | None | UndefinedType = Undefined, + isis_passive: bool | None | UndefinedType = Undefined, + isis_metric: int | None | UndefinedType = Undefined, + isis_network_point_to_point: bool | None | UndefinedType = Undefined, + isis_authentication: IsisAuthentication | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + no_autostate: bool | None | UndefinedType = Undefined, + vrrp_ids: VrrpIds | UndefinedType = Undefined, + ip_attached_host_route_export: IpAttachedHostRouteExport | UndefinedType = Undefined, + ipv6_attached_host_route_export: Ipv6AttachedHostRouteExport | UndefinedType = Undefined, + bfd: Bfd | UndefinedType = Undefined, + service_policy: ServicePolicy | UndefinedType = Undefined, + pvlan_mapping: str | None | UndefinedType = Undefined, + tenant: str | None | UndefinedType = Undefined, + tags: Tags | UndefinedType = Undefined, + type: str | None | UndefinedType = Undefined, + eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VlanInterfacesItem. + + + Subclass of AvdModel. + + Args: + name: VLAN interface name like "Vlan123". + description: description + logging: Subclass of AvdModel. + shutdown: shutdown + vrf: VRF name. + arp_aging_timeout: In seconds. + arp_cache_dynamic_capacity: arp_cache_dynamic_capacity + arp_gratuitous_accept: arp_gratuitous_accept + arp_monitor_mac_address: arp_monitor_mac_address + ip_proxy_arp: ip_proxy_arp + ip_directed_broadcast: ip_directed_broadcast + ip_address: IPv4_address/Mask. + ip_address_secondaries: Subclass of AvdList with `str` items. + ip_virtual_router_addresses: Subclass of AvdList with `str` items. + ip_address_virtual: IPv4_address/Mask. + ip_address_virtual_secondaries: Subclass of AvdList with `str` items. + ip_verify_unicast_source_reachable_via: ip_verify_unicast_source_reachable_via + ip_igmp: ip_igmp + ip_igmp_version: ip_igmp_version + ip_igmp_host_proxy: Subclass of AvdModel. + ip_helpers: + List of DHCP servers. + + Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is + `ip_helper` (`str`). + ip_dhcp_relay_all_subnets: Allow forwarding requests with secondary IP addresses in the gateway address "giaddr" field. + ip_nat: Subclass of AvdModel. + ipv6_enable: ipv6_enable + ipv6_address: IPv6_address/Mask. + ipv6_address_virtuals: + The new "ipv6_address_virtuals" key support multiple virtual ipv6 addresses. + + Subclass of AvdList + with `str` items. + ipv6_address_link_local: IPv6_address/Mask. + ipv6_virtual_router_addresses: + Improved "VARPv6" data model to support multiple VARPv6 addresses. + + Subclass of AvdList with `str` + items. + ipv6_nd_ra_disabled: ipv6_nd_ra_disabled + ipv6_nd_managed_config_flag: ipv6_nd_managed_config_flag + ipv6_nd_other_config_flag: Set the "other stateful configuration" flag in IPv6 router advertisements. + ipv6_nd_cache: + IPv6 neighbor cache options. + + Subclass of AvdModel. + ipv6_nd_prefixes: Subclass of AvdIndexedList with `Ipv6NdPrefixesItem` items. Primary key is `ipv6_prefix` (`str`). + ipv6_dhcp_relay_destinations: + Subclass of AvdIndexedList with `Ipv6DhcpRelayDestinationsItem` items. Primary key is `address` + (`str`). + ipv6_dhcp_relay_all_subnets: Allow forwarding requests with additional IPv6 addresses in the gateway address "giaddr" field. + access_group_in: IPv4 access-list name. + access_group_out: IPv4 access-list name. + ipv6_access_group_in: IPv6 access-list name. + ipv6_access_group_out: IPv6 access-list name. + multicast: Subclass of AvdModel. + ospf_network_point_to_point: ospf_network_point_to_point + ospf_area: ospf_area + ospf_cost: ospf_cost + ospf_authentication: ospf_authentication + ospf_authentication_key: Encrypted password used for simple authentication. + ospf_message_digest_keys: + Keys used for message-digest authentication. + + Subclass of AvdIndexedList with + `OspfMessageDigestKeysItem` items. Primary key is `id` (`int`). + pim: Subclass of AvdModel. + isis_enable: ISIS instance name. + isis_bfd: Enable BFD for ISIS. + isis_passive: isis_passive + isis_metric: isis_metric + isis_network_point_to_point: isis_network_point_to_point + isis_authentication: Subclass of AvdModel. + mtu: mtu + no_autostate: no_autostate + vrrp_ids: + Improved "vrrp" data model to support multiple VRRP IDs. + + Subclass of AvdIndexedList with + `VrrpIdsItem` items. Primary key is `id` (`int`). + ip_attached_host_route_export: Subclass of AvdModel. + ipv6_attached_host_route_export: Subclass of AvdModel. + bfd: Subclass of AvdModel. + service_policy: Subclass of AvdModel. + pvlan_mapping: List of VLANs as string. + tenant: Key only used for documentation or validation purposes. + tags: + Key only used for documentation or validation purposes. + + Subclass of AvdList with `str` items. + type: Key only used for documentation or validation purposes. + eos_cli: Multiline EOS CLI rendered directly on the VLAN interface in the final EOS configuration. + _custom_data: _custom_data + + """ + + class VlanInterfaces(AvdIndexedList[str, VlanInterfacesItem]): + """Subclass of AvdIndexedList with `VlanInterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + VlanInterfaces._item_type = VlanInterfacesItem + + class VlanInternalOrder(AvdModel): + """Subclass of AvdModel.""" + + class Range(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"beginning": {"type": int}, "ending": {"type": int}, "_custom_data": {"type": dict}} + beginning: int + """First VLAN ID.""" + ending: int + """Last VLAN ID.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + beginning: int | UndefinedType = Undefined, + ending: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Range. + + + Subclass of AvdModel. + + Args: + beginning: First VLAN ID. + ending: Last VLAN ID. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"allocation": {"type": str}, "range": {"type": Range}, "_custom_data": {"type": dict}} + allocation: Literal["ascending", "descending"] + range: Range + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + allocation: Literal["ascending", "descending"] | UndefinedType = Undefined, + range: Range | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VlanInternalOrder. + + + Subclass of AvdModel. + + Args: + allocation: allocation + range: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class VlansItem(AvdModel): + """Subclass of AvdModel.""" + + class TrunkGroups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + TrunkGroups._item_type = str + + class PrivateVlan(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"type": {"type": str}, "primary_vlan": {"type": int}, "_custom_data": {"type": dict}} + type: Literal["community", "isolated"] | None + primary_vlan: int | None + """Primary VLAN ID.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + type: Literal["community", "isolated"] | None | UndefinedType = Undefined, + primary_vlan: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PrivateVlan. + + + Subclass of AvdModel. + + Args: + type: type + primary_vlan: Primary VLAN ID. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "name": {"type": str}, + "state": {"type": str}, + "trunk_groups": {"type": TrunkGroups}, + "private_vlan": {"type": PrivateVlan}, + "tenant": {"type": str}, + "_custom_data": {"type": dict}, + } + id: int + """VLAN ID.""" + name: str | None + """VLAN Name.""" + state: Literal["active", "suspend"] | None + trunk_groups: TrunkGroups + """Subclass of AvdList with `str` items.""" + private_vlan: PrivateVlan + """Subclass of AvdModel.""" + tenant: str | None + """Key only used for documentation or validation purposes.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + state: Literal["active", "suspend"] | None | UndefinedType = Undefined, + trunk_groups: TrunkGroups | UndefinedType = Undefined, + private_vlan: PrivateVlan | UndefinedType = Undefined, + tenant: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VlansItem. + + + Subclass of AvdModel. + + Args: + id: VLAN ID. + name: VLAN Name. + state: state + trunk_groups: Subclass of AvdList with `str` items. + private_vlan: Subclass of AvdModel. + tenant: Key only used for documentation or validation purposes. + _custom_data: _custom_data + + """ + + class Vlans(AvdIndexedList[int, VlansItem]): + """Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + Vlans._item_type = VlansItem + + class VmtracerSessionsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "url": {"type": str}, + "username": {"type": str}, + "password": {"type": str}, + "autovlan_disable": {"type": bool}, + "vrf": {"type": str}, + "source_interface": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """Vmtracer Session Name.""" + url: str | None + username: str | None + password: str | None + """Type 7 Password Hash.""" + autovlan_disable: bool | None + vrf: str | None + source_interface: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + url: str | None | UndefinedType = Undefined, + username: str | None | UndefinedType = Undefined, + password: str | None | UndefinedType = Undefined, + autovlan_disable: bool | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + source_interface: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VmtracerSessionsItem. + + + Subclass of AvdModel. + + Args: + name: Vmtracer Session Name. + url: url + username: username + password: Type 7 Password Hash. + autovlan_disable: autovlan_disable + vrf: vrf + source_interface: source_interface + _custom_data: _custom_data + + """ + + class VmtracerSessions(AvdIndexedList[str, VmtracerSessionsItem]): + """Subclass of AvdIndexedList with `VmtracerSessionsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + VmtracerSessions._item_type = VmtracerSessionsItem + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "description": {"type": str}, + "ip_routing": {"type": bool}, + "ipv6_routing": {"type": bool}, + "ip_routing_ipv6_interfaces": {"type": bool}, + "tenant": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """VRF Name.""" + description: str | None + ip_routing: bool | None + ipv6_routing: bool | None + ip_routing_ipv6_interfaces: bool | None + tenant: str | None + """Key only used for documentation or validation purposes.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + ip_routing: bool | None | UndefinedType = Undefined, + ipv6_routing: bool | None | UndefinedType = Undefined, + ip_routing_ipv6_interfaces: bool | None | UndefinedType = Undefined, + tenant: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: VRF Name. + description: description + ip_routing: ip_routing + ipv6_routing: ipv6_routing + ip_routing_ipv6_interfaces: ip_routing_ipv6_interfaces + tenant: Key only used for documentation or validation purposes. + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + class VxlanInterface(AvdModel): + """Subclass of AvdModel.""" + + class Vxlan1(AvdModel): + """Subclass of AvdModel.""" + + class Vxlan(AvdModel): + """Subclass of AvdModel.""" + + class Multicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"headend_replication": {"type": bool}, "_custom_data": {"type": dict}} + headend_replication: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, headend_replication: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Multicast. + + + Subclass of AvdModel. + + Args: + headend_replication: headend_replication + _custom_data: _custom_data + + """ + + class ControllerClient(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, enabled: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + ControllerClient. + + + Subclass of AvdModel. + + Args: + enabled: enabled + _custom_data: _custom_data + + """ + + class BfdVtepEvpn(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "interval": {"type": int}, + "min_rx": {"type": int}, + "multiplier": {"type": int}, + "prefix_list": {"type": str}, + "_custom_data": {"type": dict}, + } + interval: int | None + min_rx: int | None + multiplier: int | None + prefix_list: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | None | UndefinedType = Undefined, + min_rx: int | None | UndefinedType = Undefined, + multiplier: int | None | UndefinedType = Undefined, + prefix_list: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BfdVtepEvpn. + + + Subclass of AvdModel. + + Args: + interval: interval + min_rx: min_rx + multiplier: multiplier + prefix_list: prefix_list + _custom_data: _custom_data + + """ + + class Qos(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "dscp_propagation_encapsulation": {"type": bool}, + "ecn_propagation": {"type": bool}, + "map_dscp_to_traffic_class_decapsulation": {"type": bool}, + "_custom_data": {"type": dict}, + } + dscp_propagation_encapsulation: bool | None + ecn_propagation: bool | None + """Enable copying the ECN marking to/from encapsulated packets.""" + map_dscp_to_traffic_class_decapsulation: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dscp_propagation_encapsulation: bool | None | UndefinedType = Undefined, + ecn_propagation: bool | None | UndefinedType = Undefined, + map_dscp_to_traffic_class_decapsulation: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Qos. + + + Subclass of AvdModel. + + Args: + dscp_propagation_encapsulation: dscp_propagation_encapsulation + ecn_propagation: Enable copying the ECN marking to/from encapsulated packets. + map_dscp_to_traffic_class_decapsulation: map_dscp_to_traffic_class_decapsulation + _custom_data: _custom_data + + """ + + class VlansItem(AvdModel): + """Subclass of AvdModel.""" + + class FloodVteps(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + FloodVteps._item_type = str + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "vni": {"type": int}, + "multicast_group": {"type": str}, + "flood_vteps": {"type": FloodVteps}, + "_custom_data": {"type": dict}, + } + id: int + """VLAN ID.""" + vni: int | None + multicast_group: str | None + """IP Multicast Group Address.""" + flood_vteps: FloodVteps + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + vni: int | None | UndefinedType = Undefined, + multicast_group: str | None | UndefinedType = Undefined, + flood_vteps: FloodVteps | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VlansItem. + + + Subclass of AvdModel. + + Args: + id: VLAN ID. + vni: vni + multicast_group: IP Multicast Group Address. + flood_vteps: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class Vlans(AvdIndexedList[int, VlansItem]): + """Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + Vlans._item_type = VlansItem + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "vni": {"type": int}, "multicast_group": {"type": str}, "_custom_data": {"type": dict}} + name: str + """VRF Name.""" + vni: int | None + multicast_group: str | None + """IP Multicast Group Address.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + vni: int | None | UndefinedType = Undefined, + multicast_group: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: VRF Name. + vni: vni + multicast_group: IP Multicast Group Address. + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + class FloodVteps(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + FloodVteps._item_type = str + + _fields: ClassVar[dict] = { + "source_interface": {"type": str}, + "multicast": {"type": Multicast}, + "controller_client": {"type": ControllerClient}, + "mlag_source_interface": {"type": str}, + "udp_port": {"type": int}, + "vtep_to_vtep_bridging": {"type": bool}, + "virtual_router_encapsulation_mac_address": {"type": str}, + "bfd_vtep_evpn": {"type": BfdVtepEvpn}, + "qos": {"type": Qos}, + "vlans": {"type": Vlans}, + "vrfs": {"type": Vrfs}, + "flood_vteps": {"type": FloodVteps}, + "flood_vtep_learned_data_plane": {"type": bool}, + "_custom_data": {"type": dict}, + } + source_interface: str | None + """Source Interface Name.""" + multicast: Multicast + """Subclass of AvdModel.""" + controller_client: ControllerClient + """ + Client to CVX Controllers. + + Subclass of AvdModel. + """ + mlag_source_interface: str | None + udp_port: int | None + vtep_to_vtep_bridging: bool | None + """Enable bridging between different VTEPs in vxlan overlay.""" + virtual_router_encapsulation_mac_address: str | None + """"mlag-system-id" or ethernet_address (H.H.H).""" + bfd_vtep_evpn: BfdVtepEvpn + """Subclass of AvdModel.""" + qos: Qos + """ + For the Traffic Class to be derived based on the outer DSCP field of the incoming VxLan packet, the + core ports must be in "DSCP Trust" mode. + !!!Warning, only few hardware types with software version + >= 4.26.0 support the below knobs to configure Vxlan DSCP mapping. + + + Subclass of AvdModel. + """ + vlans: Vlans + """Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`int`).""" + vrfs: Vrfs + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + flood_vteps: FloodVteps + """Subclass of AvdList with `str` items.""" + flood_vtep_learned_data_plane: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source_interface: str | None | UndefinedType = Undefined, + multicast: Multicast | UndefinedType = Undefined, + controller_client: ControllerClient | UndefinedType = Undefined, + mlag_source_interface: str | None | UndefinedType = Undefined, + udp_port: int | None | UndefinedType = Undefined, + vtep_to_vtep_bridging: bool | None | UndefinedType = Undefined, + virtual_router_encapsulation_mac_address: str | None | UndefinedType = Undefined, + bfd_vtep_evpn: BfdVtepEvpn | UndefinedType = Undefined, + qos: Qos | UndefinedType = Undefined, + vlans: Vlans | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + flood_vteps: FloodVteps | UndefinedType = Undefined, + flood_vtep_learned_data_plane: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Vxlan. + + + Subclass of AvdModel. + + Args: + source_interface: Source Interface Name. + multicast: Subclass of AvdModel. + controller_client: + Client to CVX Controllers. + + Subclass of AvdModel. + mlag_source_interface: mlag_source_interface + udp_port: udp_port + vtep_to_vtep_bridging: Enable bridging between different VTEPs in vxlan overlay. + virtual_router_encapsulation_mac_address: "mlag-system-id" or ethernet_address (H.H.H). + bfd_vtep_evpn: Subclass of AvdModel. + qos: + For the Traffic Class to be derived based on the outer DSCP field of the incoming VxLan packet, the + core ports must be in "DSCP Trust" mode. + !!!Warning, only few hardware types with software version + >= 4.26.0 support the below knobs to configure Vxlan DSCP mapping. + + + Subclass of AvdModel. + vlans: Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`int`). + vrfs: Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`). + flood_vteps: Subclass of AvdList with `str` items. + flood_vtep_learned_data_plane: flood_vtep_learned_data_plane + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"description": {"type": str}, "vxlan": {"type": Vxlan}, "eos_cli": {"type": str}, "_custom_data": {"type": dict}} + description: str | None + vxlan: Vxlan + """Subclass of AvdModel.""" + eos_cli: str | None + """ + Multiline String with EOS CLI rendered directly on the Vxlan interface in the final EOS + configuration. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + description: str | None | UndefinedType = Undefined, + vxlan: Vxlan | UndefinedType = Undefined, + eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Vxlan1. + + + Subclass of AvdModel. + + Args: + description: description + vxlan: Subclass of AvdModel. + eos_cli: + Multiline String with EOS CLI rendered directly on the Vxlan interface in the final EOS + configuration. + _custom_data: _custom_data + + """ + + class Vxlan1(AvdModel): + """Subclass of AvdModel.""" + + class Vxlan(AvdModel): + """Subclass of AvdModel.""" + + class Multicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"headend_replication": {"type": bool}, "_custom_data": {"type": dict}} + headend_replication: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, headend_replication: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Multicast. + + + Subclass of AvdModel. + + Args: + headend_replication: headend_replication + _custom_data: _custom_data + + """ + + class ControllerClient(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, enabled: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + ControllerClient. + + + Subclass of AvdModel. + + Args: + enabled: enabled + _custom_data: _custom_data + + """ + + class BfdVtepEvpn(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "interval": {"type": int}, + "min_rx": {"type": int}, + "multiplier": {"type": int}, + "prefix_list": {"type": str}, + "_custom_data": {"type": dict}, + } + interval: int | None + min_rx: int | None + multiplier: int | None + prefix_list: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | None | UndefinedType = Undefined, + min_rx: int | None | UndefinedType = Undefined, + multiplier: int | None | UndefinedType = Undefined, + prefix_list: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BfdVtepEvpn. + + + Subclass of AvdModel. + + Args: + interval: interval + min_rx: min_rx + multiplier: multiplier + prefix_list: prefix_list + _custom_data: _custom_data + + """ + + class Qos(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "dscp_propagation_encapsulation": {"type": bool}, + "ecn_propagation": {"type": bool}, + "map_dscp_to_traffic_class_decapsulation": {"type": bool}, + "_custom_data": {"type": dict}, + } + dscp_propagation_encapsulation: bool | None + ecn_propagation: bool | None + """Enable copying the ECN marking to/from encapsulated packets.""" + map_dscp_to_traffic_class_decapsulation: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dscp_propagation_encapsulation: bool | None | UndefinedType = Undefined, + ecn_propagation: bool | None | UndefinedType = Undefined, + map_dscp_to_traffic_class_decapsulation: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Qos. + + + Subclass of AvdModel. + + Args: + dscp_propagation_encapsulation: dscp_propagation_encapsulation + ecn_propagation: Enable copying the ECN marking to/from encapsulated packets. + map_dscp_to_traffic_class_decapsulation: map_dscp_to_traffic_class_decapsulation + _custom_data: _custom_data + + """ + + class VlansItem(AvdModel): + """Subclass of AvdModel.""" + + class FloodVteps(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + FloodVteps._item_type = str + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "vni": {"type": int}, + "multicast_group": {"type": str}, + "flood_vteps": {"type": FloodVteps}, + "_custom_data": {"type": dict}, + } + id: int + """VLAN ID.""" + vni: int | None + multicast_group: str | None + """IP Multicast Group Address.""" + flood_vteps: FloodVteps + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + vni: int | None | UndefinedType = Undefined, + multicast_group: str | None | UndefinedType = Undefined, + flood_vteps: FloodVteps | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VlansItem. + + + Subclass of AvdModel. + + Args: + id: VLAN ID. + vni: vni + multicast_group: IP Multicast Group Address. + flood_vteps: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class Vlans(AvdIndexedList[int, VlansItem]): + """Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + Vlans._item_type = VlansItem + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "vni": {"type": int}, "multicast_group": {"type": str}, "_custom_data": {"type": dict}} + name: str + """VRF Name.""" + vni: int | None + multicast_group: str | None + """IP Multicast Group Address.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + vni: int | None | UndefinedType = Undefined, + multicast_group: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: VRF Name. + vni: vni + multicast_group: IP Multicast Group Address. + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + class FloodVteps(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + FloodVteps._item_type = str + + _fields: ClassVar[dict] = { + "source_interface": {"type": str}, + "multicast": {"type": Multicast}, + "controller_client": {"type": ControllerClient}, + "mlag_source_interface": {"type": str}, + "udp_port": {"type": int}, + "vtep_to_vtep_bridging": {"type": bool}, + "virtual_router_encapsulation_mac_address": {"type": str}, + "bfd_vtep_evpn": {"type": BfdVtepEvpn}, + "qos": {"type": Qos}, + "vlans": {"type": Vlans}, + "vrfs": {"type": Vrfs}, + "flood_vteps": {"type": FloodVteps}, + "flood_vtep_learned_data_plane": {"type": bool}, + "_custom_data": {"type": dict}, + } + source_interface: str | None + """Source Interface Name.""" + multicast: Multicast + """Subclass of AvdModel.""" + controller_client: ControllerClient + """ + Client to CVX Controllers. + + Subclass of AvdModel. + """ + mlag_source_interface: str | None + udp_port: int | None + vtep_to_vtep_bridging: bool | None + """Enable bridging between different VTEPs in vxlan overlay.""" + virtual_router_encapsulation_mac_address: str | None + """"mlag-system-id" or ethernet_address (H.H.H).""" + bfd_vtep_evpn: BfdVtepEvpn + """Subclass of AvdModel.""" + qos: Qos + """ + For the Traffic Class to be derived based on the outer DSCP field of the incoming VxLan packet, the + core ports must be in "DSCP Trust" mode. + !!!Warning, only few hardware types with software version + >= 4.26.0 support the below knobs to configure Vxlan DSCP mapping. + + + Subclass of AvdModel. + """ + vlans: Vlans + """Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`int`).""" + vrfs: Vrfs + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + flood_vteps: FloodVteps + """Subclass of AvdList with `str` items.""" + flood_vtep_learned_data_plane: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source_interface: str | None | UndefinedType = Undefined, + multicast: Multicast | UndefinedType = Undefined, + controller_client: ControllerClient | UndefinedType = Undefined, + mlag_source_interface: str | None | UndefinedType = Undefined, + udp_port: int | None | UndefinedType = Undefined, + vtep_to_vtep_bridging: bool | None | UndefinedType = Undefined, + virtual_router_encapsulation_mac_address: str | None | UndefinedType = Undefined, + bfd_vtep_evpn: BfdVtepEvpn | UndefinedType = Undefined, + qos: Qos | UndefinedType = Undefined, + vlans: Vlans | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + flood_vteps: FloodVteps | UndefinedType = Undefined, + flood_vtep_learned_data_plane: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Vxlan. + + + Subclass of AvdModel. + + Args: + source_interface: Source Interface Name. + multicast: Subclass of AvdModel. + controller_client: + Client to CVX Controllers. + + Subclass of AvdModel. + mlag_source_interface: mlag_source_interface + udp_port: udp_port + vtep_to_vtep_bridging: Enable bridging between different VTEPs in vxlan overlay. + virtual_router_encapsulation_mac_address: "mlag-system-id" or ethernet_address (H.H.H). + bfd_vtep_evpn: Subclass of AvdModel. + qos: + For the Traffic Class to be derived based on the outer DSCP field of the incoming VxLan packet, the + core ports must be in "DSCP Trust" mode. + !!!Warning, only few hardware types with software version + >= 4.26.0 support the below knobs to configure Vxlan DSCP mapping. + + + Subclass of AvdModel. + vlans: Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`int`). + vrfs: Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`). + flood_vteps: Subclass of AvdList with `str` items. + flood_vtep_learned_data_plane: flood_vtep_learned_data_plane + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"description": {"type": str}, "vxlan": {"type": Vxlan}, "eos_cli": {"type": str}, "_custom_data": {"type": dict}} + description: str | None + vxlan: Vxlan + """Subclass of AvdModel.""" + eos_cli: str | None + """ + Multiline String with EOS CLI rendered directly on the Vxlan interface in the final EOS + configuration. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + description: str | None | UndefinedType = Undefined, + vxlan: Vxlan | UndefinedType = Undefined, + eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Vxlan1. + + + Subclass of AvdModel. + + Args: + description: description + vxlan: Subclass of AvdModel. + eos_cli: + Multiline String with EOS CLI rendered directly on the Vxlan interface in the final EOS + configuration. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"vxlan1": {"type": Vxlan1}, "field_Vxlan1": {"type": Vxlan1}, "_custom_data": {"type": dict}} + _field_to_key_map: ClassVar[dict] = {"field_Vxlan1": "Vxlan1"} + _key_to_field_map: ClassVar[dict] = {"Vxlan1": "field_Vxlan1"} + vxlan1: Vxlan1 + """Subclass of AvdModel.""" + field_Vxlan1: Vxlan1 + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + vxlan1: Vxlan1 | UndefinedType = Undefined, + field_Vxlan1: Vxlan1 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VxlanInterface. + + + Subclass of AvdModel. + + Args: + vxlan1: Subclass of AvdModel. + field_Vxlan1: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "aaa_accounting": {"type": AaaAccounting}, + "aaa_authentication": {"type": AaaAuthentication}, + "aaa_authorization": {"type": AaaAuthorization}, + "aaa_root": {"type": AaaRoot}, + "aaa_server_groups": {"type": AaaServerGroups}, + "access_lists": {"type": AccessLists}, + "address_locking": {"type": AddressLocking}, + "agents": {"type": Agents}, + "aliases": {"type": str}, + "application_traffic_recognition": {"type": ApplicationTrafficRecognition}, + "arp": {"type": Arp}, + "as_path": {"type": AsPath}, + "avd_data_validation_mode": {"type": str, "default": "error"}, + "banners": {"type": Banners}, + "bgp_groups": {"type": BgpGroups}, + "boot": {"type": Boot}, + "class_maps": {"type": ClassMaps}, + "clock": {"type": Clock}, + "community_lists": {"type": CommunityLists}, + "config_comment": {"type": str}, + "config_end": {"type": bool, "default": False}, + "custom_templates": {"type": CustomTemplates}, + "cvx": {"type": Cvx}, + "daemon_terminattr": {"type": DaemonTerminattr}, + "daemons": {"type": Daemons}, + "dhcp_relay": {"type": DhcpRelay}, + "dhcp_servers": {"type": DhcpServers}, + "dns_domain": {"type": str}, + "domain_list": {"type": DomainList}, + "dot1x": {"type": Dot1x}, + "dps_interfaces": {"type": DpsInterfaces}, + "dynamic_prefix_lists": {"type": DynamicPrefixLists}, + "enable_password": {"type": EnablePassword}, + "eos_cli": {"type": str}, + "eos_cli_config_gen_configuration": {"type": EosCliConfigGenConfiguration}, + "eos_cli_config_gen_documentation": {"type": EosCliConfigGenDocumentation}, + "errdisable": {"type": Errdisable}, + "ethernet_interfaces": {"type": EthernetInterfaces}, + "event_handlers": {"type": EventHandlers}, + "event_monitor": {"type": EventMonitor}, + "flow_tracking": {"type": FlowTracking}, + "generate_default_config": {"type": bool, "default": False}, + "generate_device_documentation": {"type": bool, "default": True}, + "hardware": {"type": Hardware}, + "hardware_counters": {"type": HardwareCounters}, + "hostname": {"type": str}, + "interface_defaults": {"type": InterfaceDefaults}, + "interface_groups": {"type": InterfaceGroups}, + "interface_profiles": {"type": InterfaceProfiles}, + "ip_access_lists": {"type": IpAccessLists}, + "ip_access_lists_max_entries": {"type": int}, + "ip_community_lists": {"type": IpCommunityLists}, + "ip_dhcp_relay": {"type": IpDhcpRelay}, + "ip_dhcp_snooping": {"type": IpDhcpSnooping}, + "ip_domain_lookup": {"type": IpDomainLookup}, + "ip_extcommunity_lists": {"type": IpExtcommunityLists}, + "ip_extcommunity_lists_regexp": {"type": IpExtcommunityListsRegexp}, + "ip_ftp_client_source_interfaces": {"type": IpFtpClientSourceInterfaces}, + "ip_hardware": {"type": IpHardware}, + "ip_http_client_source_interfaces": {"type": IpHttpClientSourceInterfaces}, + "ip_icmp_redirect": {"type": bool}, + "ip_igmp_snooping": {"type": IpIgmpSnooping}, + "ip_name_servers": {"type": IpNameServers}, + "ip_nat": {"type": IpNat}, + "ip_radius_source_interfaces": {"type": IpRadiusSourceInterfaces}, + "ip_routing": {"type": bool}, + "ip_routing_ipv6_interfaces": {"type": bool}, + "ip_security": {"type": IpSecurity}, + "ip_ssh_client_source_interfaces": {"type": IpSshClientSourceInterfaces}, + "ip_tacacs_source_interfaces": {"type": IpTacacsSourceInterfaces}, + "ip_telnet_client_source_interfaces": {"type": IpTelnetClientSourceInterfaces}, + "ip_tftp_client_source_interfaces": {"type": IpTftpClientSourceInterfaces}, + "ip_virtual_router_mac_address": {"type": str}, + "ipv6_access_lists": {"type": Ipv6AccessLists}, + "ipv6_dhcp_relay": {"type": Ipv6DhcpRelay}, + "ipv6_hardware": {"type": Ipv6Hardware}, + "ipv6_icmp_redirect": {"type": bool}, + "ipv6_neighbor": {"type": Ipv6Neighbor}, + "ipv6_prefix_lists": {"type": Ipv6PrefixLists}, + "ipv6_standard_access_lists": {"type": Ipv6StandardAccessLists}, + "ipv6_static_routes": {"type": Ipv6StaticRoutes}, + "ipv6_unicast_routing": {"type": bool}, + "is_deployed": {"type": bool, "default": True}, + "l2_protocol": {"type": L2Protocol}, + "lacp": {"type": Lacp}, + "link_tracking_groups": {"type": LinkTrackingGroups}, + "lldp": {"type": Lldp}, + "load_interval": {"type": LoadInterval}, + "local_users": {"type": LocalUsers}, + "logging": {"type": Logging}, + "loopback_interfaces": {"type": LoopbackInterfaces}, + "mac_access_lists": {"type": MacAccessLists}, + "mac_address_table": {"type": MacAddressTable}, + "mac_security": {"type": MacSecurity}, + "maintenance": {"type": Maintenance}, + "management_accounts": {"type": ManagementAccounts}, + "management_api_gnmi": {"type": ManagementApiGnmi}, + "management_api_http": {"type": ManagementApiHttp}, + "management_api_models": {"type": ManagementApiModels}, + "management_console": {"type": ManagementConsole}, + "management_cvx": {"type": ManagementCvx}, + "management_defaults": {"type": ManagementDefaults}, + "management_interfaces": {"type": ManagementInterfaces}, + "management_security": {"type": ManagementSecurity}, + "management_ssh": {"type": ManagementSsh}, + "management_tech_support": {"type": ManagementTechSupport}, + "match_list_input": {"type": MatchListInput}, + "mcs_client": {"type": McsClient}, + "metadata": {"type": Metadata}, + "mlag_configuration": {"type": MlagConfiguration}, + "monitor_connectivity": {"type": MonitorConnectivity}, + "monitor_layer1": {"type": MonitorLayer1}, + "monitor_server_radius": {"type": MonitorServerRadius}, + "monitor_session_default_encapsulation_gre": {"type": MonitorSessionDefaultEncapsulationGre}, + "monitor_sessions": {"type": MonitorSessions}, + "monitor_telemetry_influx": {"type": MonitorTelemetryInflux}, + "monitor_telemetry_postcard_policy": {"type": MonitorTelemetryPostcardPolicy}, + "mpls": {"type": Mpls}, + "ntp": {"type": Ntp}, + "patch_panel": {"type": PatchPanel}, + "peer_filters": {"type": PeerFilters}, + "platform": {"type": Platform}, + "poe": {"type": Poe}, + "policy_maps": {"type": PolicyMaps}, + "port_channel_interfaces": {"type": PortChannelInterfaces}, + "prefix_lists": {"type": PrefixLists}, + "priority_flow_control": {"type": PriorityFlowControl}, + "prompt": {"type": str}, + "ptp": {"type": Ptp}, + "qos": {"type": Qos}, + "qos_profiles": {"type": QosProfiles}, + "queue_monitor_length": {"type": QueueMonitorLength}, + "queue_monitor_streaming": {"type": QueueMonitorStreaming}, + "radius_server": {"type": RadiusServer}, + "redundancy": {"type": Redundancy}, + "roles": {"type": Roles}, + "route_maps": {"type": RouteMaps}, + "router_adaptive_virtual_topology": {"type": RouterAdaptiveVirtualTopology}, + "router_bfd": {"type": RouterBfd}, + "router_bgp": {"type": RouterBgp}, + "router_general": {"type": RouterGeneral}, + "router_igmp": {"type": RouterIgmp}, + "router_internet_exit": {"type": RouterInternetExit}, + "router_isis": {"type": RouterIsis}, + "router_l2_vpn": {"type": RouterL2Vpn}, + "router_msdp": {"type": RouterMsdp}, + "router_multicast": {"type": RouterMulticast}, + "router_ospf": {"type": RouterOspf}, + "router_path_selection": {"type": RouterPathSelection}, + "router_pim_sparse_mode": {"type": RouterPimSparseMode}, + "router_segment_security": {"type": RouterSegmentSecurity}, + "router_service_insertion": {"type": RouterServiceInsertion}, + "router_traffic_engineering": {"type": RouterTrafficEngineering}, + "service_routing_configuration_bgp": {"type": ServiceRoutingConfigurationBgp}, + "service_routing_protocols_model": {"type": str}, + "service_unsupported_transceiver": {"type": ServiceUnsupportedTransceiver}, + "sflow": {"type": Sflow}, + "snmp_server": {"type": SnmpServer}, + "spanning_tree": {"type": SpanningTree}, + "standard_access_lists": {"type": StandardAccessLists}, + "static_routes": {"type": StaticRoutes}, + "stun": {"type": Stun}, + "switchport_default": {"type": SwitchportDefault}, + "switchport_port_security": {"type": SwitchportPortSecurity}, + "sync_e": {"type": SyncE}, + "system": {"type": System}, + "tacacs_servers": {"type": TacacsServers}, + "tap_aggregation": {"type": TapAggregation}, + "tcam_profile": {"type": TcamProfile}, + "terminal": {"type": Terminal}, + "trackers": {"type": Trackers}, + "traffic_policies": {"type": TrafficPolicies}, + "transceiver_qsfp_default_mode_4x10": {"type": bool, "default": True}, + "tunnel_interfaces": {"type": TunnelInterfaces}, + "virtual_source_nat_vrfs": {"type": VirtualSourceNatVrfs}, + "vlan_interfaces": {"type": VlanInterfaces}, + "vlan_internal_order": {"type": VlanInternalOrder}, + "vlans": {"type": Vlans}, + "vmtracer_sessions": {"type": VmtracerSessions}, + "vrfs": {"type": Vrfs}, + "vxlan_interface": {"type": VxlanInterface}, + "_custom_data": {"type": dict}, + } + _allow_other_keys: ClassVar[bool] = True + aaa_accounting: AaaAccounting + """Subclass of AvdModel.""" + aaa_authentication: AaaAuthentication + """Subclass of AvdModel.""" + aaa_authorization: AaaAuthorization + """Subclass of AvdModel.""" + aaa_root: AaaRoot + """Subclass of AvdModel.""" + aaa_server_groups: AaaServerGroups + """Subclass of AvdIndexedList with `AaaServerGroupsItem` items. Primary key is `name` (`str`).""" + access_lists: AccessLists + """Subclass of AvdIndexedList with `AccessListsItem` items. Primary key is `name` (`str`).""" + address_locking: AddressLocking + """Subclass of AvdModel.""" + agents: Agents + """Subclass of AvdIndexedList with `AgentsItem` items. Primary key is `name` (`str`).""" + aliases: str | None + """ + Multi-line string with one or more alias commands. + + Example: + + ```yaml + aliases: | + alias wr copy + running-config startup-config + alias siib show ip interface brief + ``` + """ + application_traffic_recognition: ApplicationTrafficRecognition + """ + Application traffic recognition configuration. + + Subclass of AvdModel. + """ + arp: Arp + """Subclass of AvdModel.""" + as_path: AsPath + """Subclass of AvdModel.""" + avd_data_validation_mode: Literal["error", "warning"] + """ + Validation Mode for AVD input data validation. + Input data validation will validate the input + variables according to the schema. + During validation, messages will generated with information about + the host(s) and key(s) which failed validation. + "error" will produce error messages and fail the + task. + "warning" will produce warning messages. + + Default value: `"error"` + """ + banners: Banners + """Subclass of AvdModel.""" + bgp_groups: BgpGroups + """Subclass of AvdIndexedList with `BgpGroupsItem` items. Primary key is `name` (`str`).""" + boot: Boot + """ + Set the Aboot password. + + + Subclass of AvdModel. + """ + class_maps: ClassMaps + """Subclass of AvdModel.""" + clock: Clock + """Subclass of AvdModel.""" + community_lists: CommunityLists + """Subclass of AvdIndexedList with `CommunityListsItem` items. Primary key is `name` (`str`).""" + config_comment: str | None + """ + Add a comment to provide information about the configuration. + This comment will be rendered at the + top of the generated configuration. + """ + config_end: bool + """ + Render `end` at the end of the configuration. + + Default value: `False` + """ + custom_templates: CustomTemplates + """ + - Custom templates can be added below the playbook directory. + - If a location above the directory is + desired, a symbolic link can be used. + - Example under the `playbooks` directory create symbolic link + with the following command: + + ```bash + ln -s ../../shared_repo/custom_avd_templates/ + ./custom_avd_templates + ``` + + - The output will be rendered at the end of the configuration. + - The + order of custom templates in the list can be important if they overlap. + - It is recommended to use a + `!` delimiter at the top of each custom template. + + Add `custom_templates` to group/host variables: + Subclass of AvdList with `str` items. + """ + cvx: Cvx + """ + CVX server features are not supported on physical switches. See `management_cvx` for client + configurations. + + Subclass of AvdModel. + """ + daemon_terminattr: DaemonTerminattr + """ + You can either provide a list of IPs/FQDNs to target on-premise Cloudvision cluster or use DNS name + for your Cloudvision as a Service instance. + Streaming to multiple clusters both on-prem and cloud + service is supported. + + !!! note + For TerminAttr version recommendation and EOS compatibility + matrix, please refer to the latest TerminAttr Release Notes + which always contain the latest + recommended versions and minimum required versions per EOS release. + + + Subclass of AvdModel. + """ + daemons: Daemons + """ + This will add a daemon to the eos configuration that is most useful when trying to run OpenConfig + clients like ocprometheus. + + Subclass of AvdIndexedList with `DaemonsItem` items. Primary key is + `name` (`str`). + """ + dhcp_relay: DhcpRelay + """Subclass of AvdModel.""" + dhcp_servers: DhcpServers + """Subclass of AvdIndexedList with `DhcpServersItem` items. Primary key is `vrf` (`str`).""" + dns_domain: str | None + """Domain Name.""" + domain_list: DomainList + """ + Search list of DNS domains. + + Subclass of AvdList with `str` items. + """ + dot1x: Dot1x + """Subclass of AvdModel.""" + dps_interfaces: DpsInterfaces + """Subclass of AvdIndexedList with `DpsInterfacesItem` items. Primary key is `name` (`str`).""" + dynamic_prefix_lists: DynamicPrefixLists + """Subclass of AvdList with `DynamicPrefixListsItem` items.""" + enable_password: EnablePassword + """Subclass of AvdModel.""" + eos_cli: str | None + """Multiline string with EOS CLI rendered directly on the root level of the final EOS configuration.""" + eos_cli_config_gen_configuration: EosCliConfigGenConfiguration + """Subclass of AvdModel.""" + eos_cli_config_gen_documentation: EosCliConfigGenDocumentation + """Subclass of AvdModel.""" + errdisable: Errdisable + """Subclass of AvdModel.""" + ethernet_interfaces: EthernetInterfaces + """Subclass of AvdIndexedList with `EthernetInterfacesItem` items. Primary key is `name` (`str`).""" + event_handlers: EventHandlers + """ + Gives the ability to monitor and react to Syslog messages. + Event Handlers provide a powerful and + flexible tool that can be used to apply self-healing actions, + customize the system behavior, and + implement workarounds to problems discovered in the field. + + + Subclass of AvdIndexedList with + `EventHandlersItem` items. Primary key is `name` (`str`). + """ + event_monitor: EventMonitor + """Subclass of AvdModel.""" + flow_tracking: FlowTracking + """Subclass of AvdModel.""" + generate_default_config: bool + """ + The `generate_default_config` knob allows to omit default EOS configuration. + This can be useful when + leveraging `eos_cli_config_gen` to generate configlets with CloudVision. + + The following commands + will be omitted when `generate_default_config` is set to `false`: + + - RANCID Content Type + - Hostname + (even if `hostname` variable is not set. Then the hostname is picked up from `inventory_hostname`) + - + Default configuration for `aaa` + - Default configuration for `enable password` + - Transceiver qsfp + default mode + - End of configuration delimiter + + Default value: `False` + """ + generate_device_documentation: bool + """Default value: `True`""" + hardware: Hardware + """Subclass of AvdModel.""" + hardware_counters: HardwareCounters + """Subclass of AvdModel.""" + hostname: str | None + interface_defaults: InterfaceDefaults + """Subclass of AvdModel.""" + interface_groups: InterfaceGroups + """Subclass of AvdIndexedList with `InterfaceGroupsItem` items. Primary key is `name` (`str`).""" + interface_profiles: InterfaceProfiles + """Subclass of AvdIndexedList with `InterfaceProfilesItem` items. Primary key is `name` (`str`).""" + ip_access_lists: IpAccessLists + """Subclass of AvdIndexedList with `IpAccessListsItem` items. Primary key is `name` (`str`).""" + ip_access_lists_max_entries: int | None + """Limit ACL entries defined under the `ip_access_lists`.""" + ip_community_lists: IpCommunityLists + """ + Communities and regexp entries MUST not be configured in the same community-list. + + + Subclass of + AvdIndexedList with `IpCommunityListsItem` items. Primary key is `name` (`str`). + """ + ip_dhcp_relay: IpDhcpRelay + """Subclass of AvdModel.""" + ip_dhcp_snooping: IpDhcpSnooping + """Subclass of AvdModel.""" + ip_domain_lookup: IpDomainLookup + """Subclass of AvdModel.""" + ip_extcommunity_lists: IpExtcommunityLists + """Subclass of AvdIndexedList with `IpExtcommunityListsItem` items. Primary key is `name` (`str`).""" + ip_extcommunity_lists_regexp: IpExtcommunityListsRegexp + """ + Subclass of AvdIndexedList with `IpExtcommunityListsRegexpItem` items. Primary key is `name` + (`str`). + """ + ip_ftp_client_source_interfaces: IpFtpClientSourceInterfaces + """Subclass of AvdList with `IpFtpClientSourceInterfacesItem` items.""" + ip_hardware: IpHardware + """Subclass of AvdModel.""" + ip_http_client_source_interfaces: IpHttpClientSourceInterfaces + """Subclass of AvdList with `IpHttpClientSourceInterfacesItem` items.""" + ip_icmp_redirect: bool | None + ip_igmp_snooping: IpIgmpSnooping + """Subclass of AvdModel.""" + ip_name_servers: IpNameServers + """Subclass of AvdList with `IpNameServersItem` items.""" + ip_nat: IpNat + """Subclass of AvdModel.""" + ip_radius_source_interfaces: IpRadiusSourceInterfaces + """Subclass of AvdList with `IpRadiusSourceInterfacesItem` items.""" + ip_routing: bool | None + ip_routing_ipv6_interfaces: bool | None + ip_security: IpSecurity + """Subclass of AvdModel.""" + ip_ssh_client_source_interfaces: IpSshClientSourceInterfaces + """Subclass of AvdList with `IpSshClientSourceInterfacesItem` items.""" + ip_tacacs_source_interfaces: IpTacacsSourceInterfaces + """Subclass of AvdList with `IpTacacsSourceInterfacesItem` items.""" + ip_telnet_client_source_interfaces: IpTelnetClientSourceInterfaces + """Subclass of AvdList with `IpTelnetClientSourceInterfacesItem` items.""" + ip_tftp_client_source_interfaces: IpTftpClientSourceInterfaces + """Subclass of AvdList with `IpTftpClientSourceInterfacesItem` items.""" + ip_virtual_router_mac_address: str | None + """MAC address (hh:hh:hh:hh:hh:hh).""" + ipv6_access_lists: Ipv6AccessLists + """Subclass of AvdIndexedList with `Ipv6AccessListsItem` items. Primary key is `name` (`str`).""" + ipv6_dhcp_relay: Ipv6DhcpRelay + """Subclass of AvdModel.""" + ipv6_hardware: Ipv6Hardware + """Subclass of AvdModel.""" + ipv6_icmp_redirect: bool | None + ipv6_neighbor: Ipv6Neighbor + """Subclass of AvdModel.""" + ipv6_prefix_lists: Ipv6PrefixLists + """Subclass of AvdIndexedList with `Ipv6PrefixListsItem` items. Primary key is `name` (`str`).""" + ipv6_standard_access_lists: Ipv6StandardAccessLists + """Subclass of AvdIndexedList with `Ipv6StandardAccessListsItem` items. Primary key is `name` (`str`).""" + ipv6_static_routes: Ipv6StaticRoutes + """Subclass of AvdList with `Ipv6StaticRoutesItem` items.""" + ipv6_unicast_routing: bool | None + is_deployed: bool + """ + Key only used for documentation or validation purposes. + + Default value: `True` + """ + l2_protocol: L2Protocol + """Subclass of AvdModel.""" + lacp: Lacp + """ + Set Link Aggregation Control Protocol (LACP) parameters. + + Subclass of AvdModel. + """ + link_tracking_groups: LinkTrackingGroups + """Subclass of AvdIndexedList with `LinkTrackingGroupsItem` items. Primary key is `name` (`str`).""" + lldp: Lldp + """Subclass of AvdModel.""" + load_interval: LoadInterval + """Subclass of AvdModel.""" + local_users: LocalUsers + """Subclass of AvdIndexedList with `LocalUsersItem` items. Primary key is `name` (`str`).""" + logging: Logging + """Subclass of AvdModel.""" + loopback_interfaces: LoopbackInterfaces + """Subclass of AvdIndexedList with `LoopbackInterfacesItem` items. Primary key is `name` (`str`).""" + mac_access_lists: MacAccessLists + """Subclass of AvdIndexedList with `MacAccessListsItem` items. Primary key is `name` (`str`).""" + mac_address_table: MacAddressTable + """Subclass of AvdModel.""" + mac_security: MacSecurity + """Subclass of AvdModel.""" + maintenance: Maintenance + """Subclass of AvdModel.""" + management_accounts: ManagementAccounts + """Subclass of AvdModel.""" + management_api_gnmi: ManagementApiGnmi + """Subclass of AvdModel.""" + management_api_http: ManagementApiHttp + """Subclass of AvdModel.""" + management_api_models: ManagementApiModels + """Subclass of AvdModel.""" + management_console: ManagementConsole + """Subclass of AvdModel.""" + management_cvx: ManagementCvx + """Subclass of AvdModel.""" + management_defaults: ManagementDefaults + """Subclass of AvdModel.""" + management_interfaces: ManagementInterfaces + """Subclass of AvdIndexedList with `ManagementInterfacesItem` items. Primary key is `name` (`str`).""" + management_security: ManagementSecurity + """Subclass of AvdModel.""" + management_ssh: ManagementSsh + """Subclass of AvdModel.""" + management_tech_support: ManagementTechSupport + """Subclass of AvdModel.""" + match_list_input: MatchListInput + """Subclass of AvdModel.""" + mcs_client: McsClient + """Subclass of AvdModel.""" + metadata: Metadata + """ + The data under `metadata` is used for documentation, validation or integration purposes. + It will not + affect the generated EOS configuration. + + Subclass of AvdModel. + """ + mlag_configuration: MlagConfiguration + """Subclass of AvdModel.""" + monitor_connectivity: MonitorConnectivity + """Subclass of AvdModel.""" + monitor_layer1: MonitorLayer1 + """ + Enable SYSLOG messages on transceiver SMBus communication failures. + + Subclass of AvdModel. + """ + monitor_server_radius: MonitorServerRadius + """ + Settings to monitor radius servers. + + Subclass of AvdModel. + """ + monitor_session_default_encapsulation_gre: MonitorSessionDefaultEncapsulationGre + """Subclass of AvdModel.""" + monitor_sessions: MonitorSessions + """Subclass of AvdList with `MonitorSessionsItem` items.""" + monitor_telemetry_influx: MonitorTelemetryInflux + """Subclass of AvdModel.""" + monitor_telemetry_postcard_policy: MonitorTelemetryPostcardPolicy + """Subclass of AvdModel.""" + mpls: Mpls + """Subclass of AvdModel.""" + ntp: Ntp + """Subclass of AvdModel.""" + patch_panel: PatchPanel + """Subclass of AvdModel.""" + peer_filters: PeerFilters + """Subclass of AvdIndexedList with `PeerFiltersItem` items. Primary key is `name` (`str`).""" + platform: Platform + """ + Every key below this point is platform dependent. + + Subclass of AvdModel. + """ + poe: Poe + """Subclass of AvdModel.""" + policy_maps: PolicyMaps + """Subclass of AvdModel.""" + port_channel_interfaces: PortChannelInterfaces + """Subclass of AvdIndexedList with `PortChannelInterfacesItem` items. Primary key is `name` (`str`).""" + prefix_lists: PrefixLists + """Subclass of AvdIndexedList with `PrefixListsItem` items. Primary key is `name` (`str`).""" + priority_flow_control: PriorityFlowControl + """ + Global Priority Flow Control settings. + + + Subclass of AvdModel. + """ + prompt: str | None + ptp: Ptp + """Subclass of AvdModel.""" + qos: Qos + """Subclass of AvdModel.""" + qos_profiles: QosProfiles + """Subclass of AvdIndexedList with `QosProfilesItem` items. Primary key is `name` (`str`).""" + queue_monitor_length: QueueMonitorLength + """Subclass of AvdModel.""" + queue_monitor_streaming: QueueMonitorStreaming + """Subclass of AvdModel.""" + radius_server: RadiusServer + """Subclass of AvdModel.""" + redundancy: Redundancy + """Subclass of AvdModel.""" + roles: Roles + """Subclass of AvdIndexedList with `RolesItem` items. Primary key is `name` (`str`).""" + route_maps: RouteMaps + """Subclass of AvdIndexedList with `RouteMapsItem` items. Primary key is `name` (`str`).""" + router_adaptive_virtual_topology: RouterAdaptiveVirtualTopology + """Subclass of AvdModel.""" + router_bfd: RouterBfd + """Subclass of AvdModel.""" + router_bgp: RouterBgp + """Subclass of AvdModel.""" + router_general: RouterGeneral + """Subclass of AvdModel.""" + router_igmp: RouterIgmp + """Subclass of AvdModel.""" + router_internet_exit: RouterInternetExit + """ + Internet-exit feature to configure internet bound service for virtual topologies. + + Subclass of + AvdModel. + """ + router_isis: RouterIsis + """Subclass of AvdModel.""" + router_l2_vpn: RouterL2Vpn + """Subclass of AvdModel.""" + router_msdp: RouterMsdp + """Subclass of AvdModel.""" + router_multicast: RouterMulticast + """Subclass of AvdModel.""" + router_ospf: RouterOspf + """Subclass of AvdModel.""" + router_path_selection: RouterPathSelection + """ + Dynamic path selection configuration. + + Subclass of AvdModel. + """ + router_pim_sparse_mode: RouterPimSparseMode + """Subclass of AvdModel.""" + router_segment_security: RouterSegmentSecurity + """Subclass of AvdModel.""" + router_service_insertion: RouterServiceInsertion + """ + Configure network services inserted to data forwarding. + + Subclass of AvdModel. + """ + router_traffic_engineering: RouterTrafficEngineering + """Subclass of AvdModel.""" + service_routing_configuration_bgp: ServiceRoutingConfigurationBgp + """Subclass of AvdModel.""" + service_routing_protocols_model: Literal["multi-agent", "ribd"] | None + service_unsupported_transceiver: ServiceUnsupportedTransceiver + """Subclass of AvdModel.""" + sflow: Sflow + """Subclass of AvdModel.""" + snmp_server: SnmpServer + """ + SNMP settings. + + Subclass of AvdModel. + """ + spanning_tree: SpanningTree + """Subclass of AvdModel.""" + standard_access_lists: StandardAccessLists + """Subclass of AvdIndexedList with `StandardAccessListsItem` items. Primary key is `name` (`str`).""" + static_routes: StaticRoutes + """Subclass of AvdList with `StaticRoutesItem` items.""" + stun: Stun + """ + STUN configuration. + + Subclass of AvdModel. + """ + switchport_default: SwitchportDefault + """Subclass of AvdModel.""" + switchport_port_security: SwitchportPortSecurity + """Subclass of AvdModel.""" + sync_e: SyncE + """Subclass of AvdModel.""" + system: System + """Subclass of AvdModel.""" + tacacs_servers: TacacsServers + """Subclass of AvdModel.""" + tap_aggregation: TapAggregation + """Subclass of AvdModel.""" + tcam_profile: TcamProfile + """Subclass of AvdModel.""" + terminal: Terminal + """Subclass of AvdModel.""" + trackers: Trackers + """Subclass of AvdIndexedList with `TrackersItem` items. Primary key is `name` (`str`).""" + traffic_policies: TrafficPolicies + """Subclass of AvdModel.""" + transceiver_qsfp_default_mode_4x10: bool + """ + On all front panel ports which support this feature, the following global configuration command + changes the QSFP mode from 40G to 4x10G (default). When set to false the command reverts the default + QSFP mode back to 40G. + + Default value: `True` + """ + tunnel_interfaces: TunnelInterfaces + """Subclass of AvdIndexedList with `TunnelInterfacesItem` items. Primary key is `name` (`str`).""" + virtual_source_nat_vrfs: VirtualSourceNatVrfs + """Subclass of AvdIndexedList with `VirtualSourceNatVrfsItem` items. Primary key is `name` (`str`).""" + vlan_interfaces: VlanInterfaces + """Subclass of AvdIndexedList with `VlanInterfacesItem` items. Primary key is `name` (`str`).""" + vlan_internal_order: VlanInternalOrder + """Subclass of AvdModel.""" + vlans: Vlans + """Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`int`).""" + vmtracer_sessions: VmtracerSessions + """Subclass of AvdIndexedList with `VmtracerSessionsItem` items. Primary key is `name` (`str`).""" + vrfs: Vrfs + """ + These keys are ignored if the name of the vrf is 'default'. + + + Subclass of AvdIndexedList with + `VrfsItem` items. Primary key is `name` (`str`). + """ + vxlan_interface: VxlanInterface + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + aaa_accounting: AaaAccounting | UndefinedType = Undefined, + aaa_authentication: AaaAuthentication | UndefinedType = Undefined, + aaa_authorization: AaaAuthorization | UndefinedType = Undefined, + aaa_root: AaaRoot | UndefinedType = Undefined, + aaa_server_groups: AaaServerGroups | UndefinedType = Undefined, + access_lists: AccessLists | UndefinedType = Undefined, + address_locking: AddressLocking | UndefinedType = Undefined, + agents: Agents | UndefinedType = Undefined, + aliases: str | None | UndefinedType = Undefined, + application_traffic_recognition: ApplicationTrafficRecognition | UndefinedType = Undefined, + arp: Arp | UndefinedType = Undefined, + as_path: AsPath | UndefinedType = Undefined, + avd_data_validation_mode: Literal["error", "warning"] | UndefinedType = Undefined, + banners: Banners | UndefinedType = Undefined, + bgp_groups: BgpGroups | UndefinedType = Undefined, + boot: Boot | UndefinedType = Undefined, + class_maps: ClassMaps | UndefinedType = Undefined, + clock: Clock | UndefinedType = Undefined, + community_lists: CommunityLists | UndefinedType = Undefined, + config_comment: str | None | UndefinedType = Undefined, + config_end: bool | UndefinedType = Undefined, + custom_templates: CustomTemplates | UndefinedType = Undefined, + cvx: Cvx | UndefinedType = Undefined, + daemon_terminattr: DaemonTerminattr | UndefinedType = Undefined, + daemons: Daemons | UndefinedType = Undefined, + dhcp_relay: DhcpRelay | UndefinedType = Undefined, + dhcp_servers: DhcpServers | UndefinedType = Undefined, + dns_domain: str | None | UndefinedType = Undefined, + domain_list: DomainList | UndefinedType = Undefined, + dot1x: Dot1x | UndefinedType = Undefined, + dps_interfaces: DpsInterfaces | UndefinedType = Undefined, + dynamic_prefix_lists: DynamicPrefixLists | UndefinedType = Undefined, + enable_password: EnablePassword | UndefinedType = Undefined, + eos_cli: str | None | UndefinedType = Undefined, + eos_cli_config_gen_configuration: EosCliConfigGenConfiguration | UndefinedType = Undefined, + eos_cli_config_gen_documentation: EosCliConfigGenDocumentation | UndefinedType = Undefined, + errdisable: Errdisable | UndefinedType = Undefined, + ethernet_interfaces: EthernetInterfaces | UndefinedType = Undefined, + event_handlers: EventHandlers | UndefinedType = Undefined, + event_monitor: EventMonitor | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + generate_default_config: bool | UndefinedType = Undefined, + generate_device_documentation: bool | UndefinedType = Undefined, + hardware: Hardware | UndefinedType = Undefined, + hardware_counters: HardwareCounters | UndefinedType = Undefined, + hostname: str | None | UndefinedType = Undefined, + interface_defaults: InterfaceDefaults | UndefinedType = Undefined, + interface_groups: InterfaceGroups | UndefinedType = Undefined, + interface_profiles: InterfaceProfiles | UndefinedType = Undefined, + ip_access_lists: IpAccessLists | UndefinedType = Undefined, + ip_access_lists_max_entries: int | None | UndefinedType = Undefined, + ip_community_lists: IpCommunityLists | UndefinedType = Undefined, + ip_dhcp_relay: IpDhcpRelay | UndefinedType = Undefined, + ip_dhcp_snooping: IpDhcpSnooping | UndefinedType = Undefined, + ip_domain_lookup: IpDomainLookup | UndefinedType = Undefined, + ip_extcommunity_lists: IpExtcommunityLists | UndefinedType = Undefined, + ip_extcommunity_lists_regexp: IpExtcommunityListsRegexp | UndefinedType = Undefined, + ip_ftp_client_source_interfaces: IpFtpClientSourceInterfaces | UndefinedType = Undefined, + ip_hardware: IpHardware | UndefinedType = Undefined, + ip_http_client_source_interfaces: IpHttpClientSourceInterfaces | UndefinedType = Undefined, + ip_icmp_redirect: bool | None | UndefinedType = Undefined, + ip_igmp_snooping: IpIgmpSnooping | UndefinedType = Undefined, + ip_name_servers: IpNameServers | UndefinedType = Undefined, + ip_nat: IpNat | UndefinedType = Undefined, + ip_radius_source_interfaces: IpRadiusSourceInterfaces | UndefinedType = Undefined, + ip_routing: bool | None | UndefinedType = Undefined, + ip_routing_ipv6_interfaces: bool | None | UndefinedType = Undefined, + ip_security: IpSecurity | UndefinedType = Undefined, + ip_ssh_client_source_interfaces: IpSshClientSourceInterfaces | UndefinedType = Undefined, + ip_tacacs_source_interfaces: IpTacacsSourceInterfaces | UndefinedType = Undefined, + ip_telnet_client_source_interfaces: IpTelnetClientSourceInterfaces | UndefinedType = Undefined, + ip_tftp_client_source_interfaces: IpTftpClientSourceInterfaces | UndefinedType = Undefined, + ip_virtual_router_mac_address: str | None | UndefinedType = Undefined, + ipv6_access_lists: Ipv6AccessLists | UndefinedType = Undefined, + ipv6_dhcp_relay: Ipv6DhcpRelay | UndefinedType = Undefined, + ipv6_hardware: Ipv6Hardware | UndefinedType = Undefined, + ipv6_icmp_redirect: bool | None | UndefinedType = Undefined, + ipv6_neighbor: Ipv6Neighbor | UndefinedType = Undefined, + ipv6_prefix_lists: Ipv6PrefixLists | UndefinedType = Undefined, + ipv6_standard_access_lists: Ipv6StandardAccessLists | UndefinedType = Undefined, + ipv6_static_routes: Ipv6StaticRoutes | UndefinedType = Undefined, + ipv6_unicast_routing: bool | None | UndefinedType = Undefined, + is_deployed: bool | UndefinedType = Undefined, + l2_protocol: L2Protocol | UndefinedType = Undefined, + lacp: Lacp | UndefinedType = Undefined, + link_tracking_groups: LinkTrackingGroups | UndefinedType = Undefined, + lldp: Lldp | UndefinedType = Undefined, + load_interval: LoadInterval | UndefinedType = Undefined, + local_users: LocalUsers | UndefinedType = Undefined, + logging: Logging | UndefinedType = Undefined, + loopback_interfaces: LoopbackInterfaces | UndefinedType = Undefined, + mac_access_lists: MacAccessLists | UndefinedType = Undefined, + mac_address_table: MacAddressTable | UndefinedType = Undefined, + mac_security: MacSecurity | UndefinedType = Undefined, + maintenance: Maintenance | UndefinedType = Undefined, + management_accounts: ManagementAccounts | UndefinedType = Undefined, + management_api_gnmi: ManagementApiGnmi | UndefinedType = Undefined, + management_api_http: ManagementApiHttp | UndefinedType = Undefined, + management_api_models: ManagementApiModels | UndefinedType = Undefined, + management_console: ManagementConsole | UndefinedType = Undefined, + management_cvx: ManagementCvx | UndefinedType = Undefined, + management_defaults: ManagementDefaults | UndefinedType = Undefined, + management_interfaces: ManagementInterfaces | UndefinedType = Undefined, + management_security: ManagementSecurity | UndefinedType = Undefined, + management_ssh: ManagementSsh | UndefinedType = Undefined, + management_tech_support: ManagementTechSupport | UndefinedType = Undefined, + match_list_input: MatchListInput | UndefinedType = Undefined, + mcs_client: McsClient | UndefinedType = Undefined, + metadata: Metadata | UndefinedType = Undefined, + mlag_configuration: MlagConfiguration | UndefinedType = Undefined, + monitor_connectivity: MonitorConnectivity | UndefinedType = Undefined, + monitor_layer1: MonitorLayer1 | UndefinedType = Undefined, + monitor_server_radius: MonitorServerRadius | UndefinedType = Undefined, + monitor_session_default_encapsulation_gre: MonitorSessionDefaultEncapsulationGre | UndefinedType = Undefined, + monitor_sessions: MonitorSessions | UndefinedType = Undefined, + monitor_telemetry_influx: MonitorTelemetryInflux | UndefinedType = Undefined, + monitor_telemetry_postcard_policy: MonitorTelemetryPostcardPolicy | UndefinedType = Undefined, + mpls: Mpls | UndefinedType = Undefined, + ntp: Ntp | UndefinedType = Undefined, + patch_panel: PatchPanel | UndefinedType = Undefined, + peer_filters: PeerFilters | UndefinedType = Undefined, + platform: Platform | UndefinedType = Undefined, + poe: Poe | UndefinedType = Undefined, + policy_maps: PolicyMaps | UndefinedType = Undefined, + port_channel_interfaces: PortChannelInterfaces | UndefinedType = Undefined, + prefix_lists: PrefixLists | UndefinedType = Undefined, + priority_flow_control: PriorityFlowControl | UndefinedType = Undefined, + prompt: str | None | UndefinedType = Undefined, + ptp: Ptp | UndefinedType = Undefined, + qos: Qos | UndefinedType = Undefined, + qos_profiles: QosProfiles | UndefinedType = Undefined, + queue_monitor_length: QueueMonitorLength | UndefinedType = Undefined, + queue_monitor_streaming: QueueMonitorStreaming | UndefinedType = Undefined, + radius_server: RadiusServer | UndefinedType = Undefined, + redundancy: Redundancy | UndefinedType = Undefined, + roles: Roles | UndefinedType = Undefined, + route_maps: RouteMaps | UndefinedType = Undefined, + router_adaptive_virtual_topology: RouterAdaptiveVirtualTopology | UndefinedType = Undefined, + router_bfd: RouterBfd | UndefinedType = Undefined, + router_bgp: RouterBgp | UndefinedType = Undefined, + router_general: RouterGeneral | UndefinedType = Undefined, + router_igmp: RouterIgmp | UndefinedType = Undefined, + router_internet_exit: RouterInternetExit | UndefinedType = Undefined, + router_isis: RouterIsis | UndefinedType = Undefined, + router_l2_vpn: RouterL2Vpn | UndefinedType = Undefined, + router_msdp: RouterMsdp | UndefinedType = Undefined, + router_multicast: RouterMulticast | UndefinedType = Undefined, + router_ospf: RouterOspf | UndefinedType = Undefined, + router_path_selection: RouterPathSelection | UndefinedType = Undefined, + router_pim_sparse_mode: RouterPimSparseMode | UndefinedType = Undefined, + router_segment_security: RouterSegmentSecurity | UndefinedType = Undefined, + router_service_insertion: RouterServiceInsertion | UndefinedType = Undefined, + router_traffic_engineering: RouterTrafficEngineering | UndefinedType = Undefined, + service_routing_configuration_bgp: ServiceRoutingConfigurationBgp | UndefinedType = Undefined, + service_routing_protocols_model: Literal["multi-agent", "ribd"] | None | UndefinedType = Undefined, + service_unsupported_transceiver: ServiceUnsupportedTransceiver | UndefinedType = Undefined, + sflow: Sflow | UndefinedType = Undefined, + snmp_server: SnmpServer | UndefinedType = Undefined, + spanning_tree: SpanningTree | UndefinedType = Undefined, + standard_access_lists: StandardAccessLists | UndefinedType = Undefined, + static_routes: StaticRoutes | UndefinedType = Undefined, + stun: Stun | UndefinedType = Undefined, + switchport_default: SwitchportDefault | UndefinedType = Undefined, + switchport_port_security: SwitchportPortSecurity | UndefinedType = Undefined, + sync_e: SyncE | UndefinedType = Undefined, + system: System | UndefinedType = Undefined, + tacacs_servers: TacacsServers | UndefinedType = Undefined, + tap_aggregation: TapAggregation | UndefinedType = Undefined, + tcam_profile: TcamProfile | UndefinedType = Undefined, + terminal: Terminal | UndefinedType = Undefined, + trackers: Trackers | UndefinedType = Undefined, + traffic_policies: TrafficPolicies | UndefinedType = Undefined, + transceiver_qsfp_default_mode_4x10: bool | UndefinedType = Undefined, + tunnel_interfaces: TunnelInterfaces | UndefinedType = Undefined, + virtual_source_nat_vrfs: VirtualSourceNatVrfs | UndefinedType = Undefined, + vlan_interfaces: VlanInterfaces | UndefinedType = Undefined, + vlan_internal_order: VlanInternalOrder | UndefinedType = Undefined, + vlans: Vlans | UndefinedType = Undefined, + vmtracer_sessions: VmtracerSessions | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + vxlan_interface: VxlanInterface | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EosCliConfigGen. + + + Subclass of AvdModel. + + Args: + aaa_accounting: Subclass of AvdModel. + aaa_authentication: Subclass of AvdModel. + aaa_authorization: Subclass of AvdModel. + aaa_root: Subclass of AvdModel. + aaa_server_groups: Subclass of AvdIndexedList with `AaaServerGroupsItem` items. Primary key is `name` (`str`). + access_lists: Subclass of AvdIndexedList with `AccessListsItem` items. Primary key is `name` (`str`). + address_locking: Subclass of AvdModel. + agents: Subclass of AvdIndexedList with `AgentsItem` items. Primary key is `name` (`str`). + aliases: + Multi-line string with one or more alias commands. + + Example: # fmt: skip + + ```yaml + aliases: | + alias wr copy + running-config startup-config + alias siib show ip interface brief + ``` + application_traffic_recognition: + Application traffic recognition configuration. + + Subclass of AvdModel. + arp: Subclass of AvdModel. + as_path: Subclass of AvdModel. + avd_data_validation_mode: + Validation Mode for AVD input data validation. + Input data validation will validate the input + variables according to the schema. + During validation, messages will generated with information about + the host(s) and key(s) which failed validation. + "error" will produce error messages and fail the + task. + "warning" will produce warning messages. + banners: Subclass of AvdModel. + bgp_groups: Subclass of AvdIndexedList with `BgpGroupsItem` items. Primary key is `name` (`str`). + boot: + Set the Aboot password. + + + Subclass of AvdModel. + class_maps: Subclass of AvdModel. + clock: Subclass of AvdModel. + community_lists: Subclass of AvdIndexedList with `CommunityListsItem` items. Primary key is `name` (`str`). + config_comment: + Add a comment to provide information about the configuration. + This comment will be rendered at the + top of the generated configuration. + config_end: Render `end` at the end of the configuration. + custom_templates: + - Custom templates can be added below the playbook directory. + - If a location above the directory is + desired, a symbolic link can be used. + - Example under the `playbooks` directory create symbolic link + with the following command: + + ```bash + ln -s ../../shared_repo/custom_avd_templates/ + ./custom_avd_templates + ``` + + - The output will be rendered at the end of the configuration. + - The + order of custom templates in the list can be important if they overlap. + - It is recommended to use a + `!` delimiter at the top of each custom template. + + Add `custom_templates` to group/host variables: + Subclass of AvdList with `str` items. + cvx: + CVX server features are not supported on physical switches. See `management_cvx` for client + configurations. + + Subclass of AvdModel. + daemon_terminattr: + You can either provide a list of IPs/FQDNs to target on-premise Cloudvision cluster or use DNS name + for your Cloudvision as a Service instance. + Streaming to multiple clusters both on-prem and cloud + service is supported. + + !!! note + For TerminAttr version recommendation and EOS compatibility + matrix, please refer to the latest TerminAttr Release Notes + which always contain the latest + recommended versions and minimum required versions per EOS release. + + + Subclass of AvdModel. + daemons: + This will add a daemon to the eos configuration that is most useful when trying to run OpenConfig + clients like ocprometheus. + + Subclass of AvdIndexedList with `DaemonsItem` items. Primary key is + `name` (`str`). + dhcp_relay: Subclass of AvdModel. + dhcp_servers: Subclass of AvdIndexedList with `DhcpServersItem` items. Primary key is `vrf` (`str`). + dns_domain: Domain Name. + domain_list: + Search list of DNS domains. + + Subclass of AvdList with `str` items. + dot1x: Subclass of AvdModel. + dps_interfaces: Subclass of AvdIndexedList with `DpsInterfacesItem` items. Primary key is `name` (`str`). + dynamic_prefix_lists: Subclass of AvdList with `DynamicPrefixListsItem` items. + enable_password: Subclass of AvdModel. + eos_cli: Multiline string with EOS CLI rendered directly on the root level of the final EOS configuration. + eos_cli_config_gen_configuration: Subclass of AvdModel. + eos_cli_config_gen_documentation: Subclass of AvdModel. + errdisable: Subclass of AvdModel. + ethernet_interfaces: Subclass of AvdIndexedList with `EthernetInterfacesItem` items. Primary key is `name` (`str`). + event_handlers: + Gives the ability to monitor and react to Syslog messages. + Event Handlers provide a powerful and + flexible tool that can be used to apply self-healing actions, + customize the system behavior, and + implement workarounds to problems discovered in the field. + + + Subclass of AvdIndexedList with + `EventHandlersItem` items. Primary key is `name` (`str`). + event_monitor: Subclass of AvdModel. + flow_tracking: Subclass of AvdModel. + generate_default_config: + The `generate_default_config` knob allows to omit default EOS configuration. + This can be useful when + leveraging `eos_cli_config_gen` to generate configlets with CloudVision. + + The following commands + will be omitted when `generate_default_config` is set to `false`: + + - RANCID Content Type + - Hostname + (even if `hostname` variable is not set. Then the hostname is picked up from `inventory_hostname`) + - + Default configuration for `aaa` + - Default configuration for `enable password` + - Transceiver qsfp + default mode + - End of configuration delimiter + generate_device_documentation: generate_device_documentation + hardware: Subclass of AvdModel. + hardware_counters: Subclass of AvdModel. + hostname: hostname + interface_defaults: Subclass of AvdModel. + interface_groups: Subclass of AvdIndexedList with `InterfaceGroupsItem` items. Primary key is `name` (`str`). + interface_profiles: Subclass of AvdIndexedList with `InterfaceProfilesItem` items. Primary key is `name` (`str`). + ip_access_lists: Subclass of AvdIndexedList with `IpAccessListsItem` items. Primary key is `name` (`str`). + ip_access_lists_max_entries: Limit ACL entries defined under the `ip_access_lists`. + ip_community_lists: + Communities and regexp entries MUST not be configured in the same community-list. + + + Subclass of + AvdIndexedList with `IpCommunityListsItem` items. Primary key is `name` (`str`). + ip_dhcp_relay: Subclass of AvdModel. + ip_dhcp_snooping: Subclass of AvdModel. + ip_domain_lookup: Subclass of AvdModel. + ip_extcommunity_lists: Subclass of AvdIndexedList with `IpExtcommunityListsItem` items. Primary key is `name` (`str`). + ip_extcommunity_lists_regexp: + Subclass of AvdIndexedList with `IpExtcommunityListsRegexpItem` items. Primary key is `name` + (`str`). + ip_ftp_client_source_interfaces: Subclass of AvdList with `IpFtpClientSourceInterfacesItem` items. + ip_hardware: Subclass of AvdModel. + ip_http_client_source_interfaces: Subclass of AvdList with `IpHttpClientSourceInterfacesItem` items. + ip_icmp_redirect: ip_icmp_redirect + ip_igmp_snooping: Subclass of AvdModel. + ip_name_servers: Subclass of AvdList with `IpNameServersItem` items. + ip_nat: Subclass of AvdModel. + ip_radius_source_interfaces: Subclass of AvdList with `IpRadiusSourceInterfacesItem` items. + ip_routing: ip_routing + ip_routing_ipv6_interfaces: ip_routing_ipv6_interfaces + ip_security: Subclass of AvdModel. + ip_ssh_client_source_interfaces: Subclass of AvdList with `IpSshClientSourceInterfacesItem` items. + ip_tacacs_source_interfaces: Subclass of AvdList with `IpTacacsSourceInterfacesItem` items. + ip_telnet_client_source_interfaces: Subclass of AvdList with `IpTelnetClientSourceInterfacesItem` items. + ip_tftp_client_source_interfaces: Subclass of AvdList with `IpTftpClientSourceInterfacesItem` items. + ip_virtual_router_mac_address: MAC address (hh:hh:hh:hh:hh:hh). + ipv6_access_lists: Subclass of AvdIndexedList with `Ipv6AccessListsItem` items. Primary key is `name` (`str`). + ipv6_dhcp_relay: Subclass of AvdModel. + ipv6_hardware: Subclass of AvdModel. + ipv6_icmp_redirect: ipv6_icmp_redirect + ipv6_neighbor: Subclass of AvdModel. + ipv6_prefix_lists: Subclass of AvdIndexedList with `Ipv6PrefixListsItem` items. Primary key is `name` (`str`). + ipv6_standard_access_lists: Subclass of AvdIndexedList with `Ipv6StandardAccessListsItem` items. Primary key is `name` (`str`). + ipv6_static_routes: Subclass of AvdList with `Ipv6StaticRoutesItem` items. + ipv6_unicast_routing: ipv6_unicast_routing + is_deployed: Key only used for documentation or validation purposes. + l2_protocol: Subclass of AvdModel. + lacp: + Set Link Aggregation Control Protocol (LACP) parameters. + + Subclass of AvdModel. + link_tracking_groups: Subclass of AvdIndexedList with `LinkTrackingGroupsItem` items. Primary key is `name` (`str`). + lldp: Subclass of AvdModel. + load_interval: Subclass of AvdModel. + local_users: Subclass of AvdIndexedList with `LocalUsersItem` items. Primary key is `name` (`str`). + logging: Subclass of AvdModel. + loopback_interfaces: Subclass of AvdIndexedList with `LoopbackInterfacesItem` items. Primary key is `name` (`str`). + mac_access_lists: Subclass of AvdIndexedList with `MacAccessListsItem` items. Primary key is `name` (`str`). + mac_address_table: Subclass of AvdModel. + mac_security: Subclass of AvdModel. + maintenance: Subclass of AvdModel. + management_accounts: Subclass of AvdModel. + management_api_gnmi: Subclass of AvdModel. + management_api_http: Subclass of AvdModel. + management_api_models: Subclass of AvdModel. + management_console: Subclass of AvdModel. + management_cvx: Subclass of AvdModel. + management_defaults: Subclass of AvdModel. + management_interfaces: Subclass of AvdIndexedList with `ManagementInterfacesItem` items. Primary key is `name` (`str`). + management_security: Subclass of AvdModel. + management_ssh: Subclass of AvdModel. + management_tech_support: Subclass of AvdModel. + match_list_input: Subclass of AvdModel. + mcs_client: Subclass of AvdModel. + metadata: + The data under `metadata` is used for documentation, validation or integration purposes. + It will not + affect the generated EOS configuration. + + Subclass of AvdModel. + mlag_configuration: Subclass of AvdModel. + monitor_connectivity: Subclass of AvdModel. + monitor_layer1: + Enable SYSLOG messages on transceiver SMBus communication failures. + + Subclass of AvdModel. + monitor_server_radius: + Settings to monitor radius servers. + + Subclass of AvdModel. + monitor_session_default_encapsulation_gre: Subclass of AvdModel. + monitor_sessions: Subclass of AvdList with `MonitorSessionsItem` items. + monitor_telemetry_influx: Subclass of AvdModel. + monitor_telemetry_postcard_policy: Subclass of AvdModel. + mpls: Subclass of AvdModel. + ntp: Subclass of AvdModel. + patch_panel: Subclass of AvdModel. + peer_filters: Subclass of AvdIndexedList with `PeerFiltersItem` items. Primary key is `name` (`str`). + platform: + Every key below this point is platform dependent. + + Subclass of AvdModel. + poe: Subclass of AvdModel. + policy_maps: Subclass of AvdModel. + port_channel_interfaces: Subclass of AvdIndexedList with `PortChannelInterfacesItem` items. Primary key is `name` (`str`). + prefix_lists: Subclass of AvdIndexedList with `PrefixListsItem` items. Primary key is `name` (`str`). + priority_flow_control: + Global Priority Flow Control settings. + + + Subclass of AvdModel. + prompt: prompt + ptp: Subclass of AvdModel. + qos: Subclass of AvdModel. + qos_profiles: Subclass of AvdIndexedList with `QosProfilesItem` items. Primary key is `name` (`str`). + queue_monitor_length: Subclass of AvdModel. + queue_monitor_streaming: Subclass of AvdModel. + radius_server: Subclass of AvdModel. + redundancy: Subclass of AvdModel. + roles: Subclass of AvdIndexedList with `RolesItem` items. Primary key is `name` (`str`). + route_maps: Subclass of AvdIndexedList with `RouteMapsItem` items. Primary key is `name` (`str`). + router_adaptive_virtual_topology: Subclass of AvdModel. + router_bfd: Subclass of AvdModel. + router_bgp: Subclass of AvdModel. + router_general: Subclass of AvdModel. + router_igmp: Subclass of AvdModel. + router_internet_exit: + Internet-exit feature to configure internet bound service for virtual topologies. + + Subclass of + AvdModel. + router_isis: Subclass of AvdModel. + router_l2_vpn: Subclass of AvdModel. + router_msdp: Subclass of AvdModel. + router_multicast: Subclass of AvdModel. + router_ospf: Subclass of AvdModel. + router_path_selection: + Dynamic path selection configuration. + + Subclass of AvdModel. + router_pim_sparse_mode: Subclass of AvdModel. + router_segment_security: Subclass of AvdModel. + router_service_insertion: + Configure network services inserted to data forwarding. + + Subclass of AvdModel. + router_traffic_engineering: Subclass of AvdModel. + service_routing_configuration_bgp: Subclass of AvdModel. + service_routing_protocols_model: service_routing_protocols_model + service_unsupported_transceiver: Subclass of AvdModel. + sflow: Subclass of AvdModel. + snmp_server: + SNMP settings. + + Subclass of AvdModel. + spanning_tree: Subclass of AvdModel. + standard_access_lists: Subclass of AvdIndexedList with `StandardAccessListsItem` items. Primary key is `name` (`str`). + static_routes: Subclass of AvdList with `StaticRoutesItem` items. + stun: + STUN configuration. + + Subclass of AvdModel. + switchport_default: Subclass of AvdModel. + switchport_port_security: Subclass of AvdModel. + sync_e: Subclass of AvdModel. + system: Subclass of AvdModel. + tacacs_servers: Subclass of AvdModel. + tap_aggregation: Subclass of AvdModel. + tcam_profile: Subclass of AvdModel. + terminal: Subclass of AvdModel. + trackers: Subclass of AvdIndexedList with `TrackersItem` items. Primary key is `name` (`str`). + traffic_policies: Subclass of AvdModel. + transceiver_qsfp_default_mode_4x10: + On all front panel ports which support this feature, the following global configuration command + changes the QSFP mode from 40G to 4x10G (default). When set to false the command reverts the default + QSFP mode back to 40G. + tunnel_interfaces: Subclass of AvdIndexedList with `TunnelInterfacesItem` items. Primary key is `name` (`str`). + virtual_source_nat_vrfs: Subclass of AvdIndexedList with `VirtualSourceNatVrfsItem` items. Primary key is `name` (`str`). + vlan_interfaces: Subclass of AvdIndexedList with `VlanInterfacesItem` items. Primary key is `name` (`str`). + vlan_internal_order: Subclass of AvdModel. + vlans: Subclass of AvdIndexedList with `VlansItem` items. Primary key is `id` (`int`). + vmtracer_sessions: Subclass of AvdIndexedList with `VmtracerSessionsItem` items. Primary key is `name` (`str`). + vrfs: + These keys are ignored if the name of the vrf is 'default'. + + + Subclass of AvdIndexedList with + `VrfsItem` items. Primary key is `name` (`str`). + vxlan_interface: Subclass of AvdModel. + _custom_data: _custom_data + + """ diff --git a/python-avd/pyavd/_eos_designs/avdfacts.py b/python-avd/pyavd/_eos_designs/avdfacts.py index 94bc45d2cd9..7933a8671fb 100644 --- a/python-avd/pyavd/_eos_designs/avdfacts.py +++ b/python-avd/pyavd/_eos_designs/avdfacts.py @@ -7,15 +7,19 @@ from typing import TYPE_CHECKING, Any if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + from .shared_utils import SharedUtils class AvdFacts: _hostvars: dict + inputs: EosDesigns shared_utils: SharedUtils - def __init__(self, hostvars: dict, shared_utils: SharedUtils) -> None: + def __init__(self, hostvars: dict, inputs: EosDesigns, shared_utils: SharedUtils) -> None: self._hostvars = hostvars + self.inputs = inputs self.shared_utils = shared_utils @classmethod diff --git a/python-avd/pyavd/_eos_designs/eos_designs_facts/__init__.py b/python-avd/pyavd/_eos_designs/eos_designs_facts/__init__.py index 6b6de7a8b15..a4ba16a19f5 100644 --- a/python-avd/pyavd/_eos_designs/eos_designs_facts/__init__.py +++ b/python-avd/pyavd/_eos_designs/eos_designs_facts/__init__.py @@ -7,7 +7,6 @@ from pyavd._eos_designs.avdfacts import AvdFacts from pyavd._errors import AristaAvdError -from pyavd._utils import get from .mlag import MlagMixin from .overlay import OverlayMixin @@ -47,7 +46,7 @@ def platform(self) -> str | None: @cached_property def is_deployed(self) -> bool: """Exposed in avd_switch_facts.""" - return self.shared_utils.is_deployed + return self.inputs.is_deployed @cached_property def serial_number(self) -> str | None: @@ -62,7 +61,7 @@ def mgmt_interface(self) -> str | None: @cached_property def mgmt_ip(self) -> str | None: """Exposed in avd_switch_facts.""" - return self.shared_utils.mgmt_ip + return self.shared_utils.node_config.mgmt_ip @cached_property def mpls_lsr(self) -> bool: @@ -80,8 +79,8 @@ def evpn_multicast(self) -> bool | None: """ if "evpn" not in self.shared_utils.overlay_address_families: return None - if get(self._hostvars, "evpn_multicast") is True and self.shared_utils.vtep is True: - if not (self.shared_utils.underlay_multicast is True and self.shared_utils.igmp_snooping_enabled is not False): + if self.inputs.evpn_multicast and self.shared_utils.vtep: + if not (self.shared_utils.underlay_multicast and self.shared_utils.igmp_snooping_enabled): msg = "'evpn_multicast: True' is only supported in combination with 'underlay_multicast: True' and 'igmp_snooping_enabled : True'" raise AristaAvdError(msg) @@ -96,7 +95,7 @@ def evpn_multicast(self) -> bool | None: @cached_property def loopback_ipv4_pool(self) -> str | None: """Exposed in avd_switch_facts.""" - if self.shared_utils.underlay_router is True: + if self.shared_utils.underlay_router: return self.shared_utils.loopback_ipv4_pool return None @@ -104,14 +103,14 @@ def loopback_ipv4_pool(self) -> str | None: def uplink_ipv4_pool(self) -> str | None: """Exposed in avd_switch_facts.""" if self.shared_utils.underlay_router: - return self.shared_utils.uplink_ipv4_pool + return self.shared_utils.node_config.uplink_ipv4_pool return None @cached_property - def downlink_pools(self) -> dict | None: + def downlink_pools(self) -> list | None: """Exposed in avd_switch_facts.""" if self.shared_utils.underlay_router: - return self.shared_utils.downlink_pools + return [downlink_pool._as_dict() for downlink_pool in self.shared_utils.node_config.downlink_pools] return None @cached_property @@ -137,44 +136,46 @@ def vtep_loopback_ipv4_pool(self) -> str | None: def inband_mgmt_subnet(self) -> str | None: """Exposed in avd_switch_facts.""" if self.shared_utils.configure_parent_for_inband_mgmt: - return self.shared_utils.inband_mgmt_subnet + return self.shared_utils.node_config.inband_mgmt_subnet return None @cached_property def inband_mgmt_ipv6_subnet(self) -> str | None: """Exposed in avd_switch_facts.""" if self.shared_utils.configure_parent_for_inband_mgmt_ipv6: - return self.shared_utils.inband_mgmt_ipv6_subnet + return self.shared_utils.node_config.inband_mgmt_ipv6_subnet return None @cached_property def inband_mgmt_vlan(self) -> int | None: """Exposed in avd_switch_facts.""" if self.shared_utils.configure_parent_for_inband_mgmt or self.shared_utils.configure_parent_for_inband_mgmt_ipv6: - return self.shared_utils.inband_mgmt_vlan + return self.shared_utils.node_config.inband_mgmt_vlan return None @cached_property def inband_ztp(self) -> bool | None: """Exposed in avd_switch_facts.""" - return self.shared_utils.inband_ztp + return self.shared_utils.node_config.inband_ztp @cached_property def inband_ztp_vlan(self) -> int | None: """Exposed in avd_switch_facts.""" - if self.shared_utils.inband_ztp: - return self.shared_utils.inband_mgmt_vlan + if self.shared_utils.node_config.inband_ztp: + return self.shared_utils.node_config.inband_mgmt_vlan return None @cached_property def inband_ztp_lacp_fallback_delay(self) -> int | None: """Exposed in avd_switch_facts.""" - return self.shared_utils.inband_ztp_lacp_fallback_delay + if self.shared_utils.node_config.inband_ztp: + return self.shared_utils.node_config.inband_ztp_lacp_fallback_delay + return None @cached_property def dc_name(self) -> str | None: """Exposed in avd_switch_facts.""" - return self.shared_utils.dc_name + return self.inputs.dc_name @cached_property def group(self) -> str | None: @@ -211,16 +212,18 @@ def pod(self) -> str: Used for fabric docs """ - return self.shared_utils.pod_name or self.shared_utils.dc_name or self.shared_utils.fabric_name + return self.inputs.pod_name or self.inputs.dc_name or self.shared_utils.fabric_name @cached_property - def connected_endpoints_keys(self) -> list: + def connected_endpoints_keys(self) -> list[dict]: """ + List of connected_endpoints_keys in use on this device. + Exposed in avd_switch_facts. Used for fabric docs """ - return self.shared_utils.connected_endpoints_keys + return [entry._as_dict() for entry in self.inputs.connected_endpoints_keys if entry.key in self.inputs._dynamic_keys.connected_endpoints] @cached_property def port_profile_names(self) -> list: @@ -229,4 +232,4 @@ def port_profile_names(self) -> list: Used for fabric docs """ - return [{"profile": profile["profile"], "parent_profile": profile.get("parent_profile")} for profile in self.shared_utils.port_profiles] + return [{"profile": profile.profile, "parent_profile": profile.parent_profile} for profile in self.inputs.port_profiles] diff --git a/python-avd/pyavd/_eos_designs/eos_designs_facts/mlag.py b/python-avd/pyavd/_eos_designs/eos_designs_facts/mlag.py index 93541b9aac3..2385f0e6646 100644 --- a/python-avd/pyavd/_eos_designs/eos_designs_facts/mlag.py +++ b/python-avd/pyavd/_eos_designs/eos_designs_facts/mlag.py @@ -56,7 +56,7 @@ def mlag_l3_ip(self: EosDesignsFacts) -> str | None: if ( self.shared_utils.mlag_l3 and self.shared_utils.mlag_peer_l3_vlan is not None - and not (self.shared_utils.underlay_rfc5549 and self.shared_utils.overlay_mlag_rfc5549) + and not (self.inputs.underlay_rfc5549 and self.inputs.overlay_mlag_rfc5549) ): return self.shared_utils.mlag_l3_ip return None diff --git a/python-avd/pyavd/_eos_designs/eos_designs_facts/overlay.py b/python-avd/pyavd/_eos_designs/eos_designs_facts/overlay.py index e3f25e0f698..b9c22fa0d4f 100644 --- a/python-avd/pyavd/_eos_designs/eos_designs_facts/overlay.py +++ b/python-avd/pyavd/_eos_designs/eos_designs_facts/overlay.py @@ -6,8 +6,6 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import get - if TYPE_CHECKING: from . import EosDesignsFacts @@ -40,8 +38,8 @@ def evpn_route_servers(self: EosDesignsFacts) -> list: """ if self.shared_utils.underlay_router is True: if self.evpn_role == "client": - return get(self.shared_utils.switch_data_combined, "evpn_route_servers", default=self.shared_utils.uplink_switches) - return get(self.shared_utils.switch_data_combined, "evpn_route_servers") + return self.shared_utils.node_config.evpn_route_servers or self.shared_utils.uplink_switches + return self.shared_utils.node_config.evpn_route_servers return [] @cached_property @@ -50,7 +48,7 @@ def mpls_route_reflectors(self: EosDesignsFacts) -> list | None: if self.shared_utils.underlay_router is True and ( self.mpls_overlay_role in ["client", "server"] or (self.evpn_role in ["client", "server"] and self.overlay["evpn_mpls"]) ): - return get(self.shared_utils.switch_data_combined, "mpls_route_reflectors") + return self.shared_utils.node_config.mpls_route_reflectors return None @cached_property diff --git a/python-avd/pyavd/_eos_designs/eos_designs_facts/short_esi.py b/python-avd/pyavd/_eos_designs/eos_designs_facts/short_esi.py index 1ce8b8f2e0a..7ce205e696b 100644 --- a/python-avd/pyavd/_eos_designs/eos_designs_facts/short_esi.py +++ b/python-avd/pyavd/_eos_designs/eos_designs_facts/short_esi.py @@ -8,7 +8,7 @@ from hashlib import sha256 from typing import TYPE_CHECKING -from pyavd._utils import default, get +from pyavd._utils import default if TYPE_CHECKING: from . import EosDesignsFacts @@ -23,7 +23,7 @@ class ShortEsiMixin: """ @cached_property - def _short_esi(self: EosDesignsFacts) -> str: + def _short_esi(self: EosDesignsFacts) -> str | None: """ If short_esi is set to "auto" we will use sha256 to create a unique short_esi value based on various uplink information. @@ -33,11 +33,11 @@ def _short_esi(self: EosDesignsFacts) -> str: # On the MLAG Secondary use short-esi from MLAG primary if self.shared_utils.mlag_role == "secondary" and (peer_short_esi := self.shared_utils.mlag_peer_facts._short_esi) is not None: return peer_short_esi - short_esi = get(self.shared_utils.switch_data_combined, "short_esi") + short_esi = self.shared_utils.node_config.short_esi if short_esi == "auto": esi_seed_1 = "".join(self.shared_utils.uplink_switches[:2]) esi_seed_2 = "".join(self.shared_utils.uplink_switch_interfaces[:2]) - esi_seed_3 = "".join(default(self.shared_utils.uplink_interfaces, [])[:2]) + esi_seed_3 = "".join(self.shared_utils.uplink_interfaces[:2]) esi_seed_4 = default(self.shared_utils.group, "") esi_hash = sha256(f"{esi_seed_1}{esi_seed_2}{esi_seed_3}{esi_seed_4}".encode()).hexdigest() short_esi = re.sub(r"([0-9a-f]{4})", r"\1:", esi_hash)[:14] 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 410f0f5fe63..e7c779df8e8 100644 --- a/python-avd/pyavd/_eos_designs/eos_designs_facts/uplinks.py +++ b/python-avd/pyavd/_eos_designs/eos_designs_facts/uplinks.py @@ -8,7 +8,7 @@ from typing import TYPE_CHECKING from pyavd._errors import AristaAvdError -from pyavd._utils import append_if_not_duplicate, get +from pyavd._utils import append_if_not_duplicate from pyavd.j2filters import list_compress, natural_sort, range_expand if TYPE_CHECKING: @@ -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: @@ -45,7 +45,7 @@ def _uplink_port_channel_id(self: EosDesignsFacts) -> int: For MLAG primary validate that the port-channel id falls within 1-2000 since we also use this ID as MLAG ID. """ - uplink_port_channel_id = get(self.shared_utils.switch_data_combined, "uplink_port_channel_id") + uplink_port_channel_id = self.shared_utils.node_config.uplink_port_channel_id if self.shared_utils.mlag_role == "secondary": # MLAG Secondary @@ -84,7 +84,7 @@ def _uplink_switch_port_channel_id(self: EosDesignsFacts) -> int: If the *uplink_switch* is in MLAG, validate that the port-channel id falls within 1-2000 since we also use this ID as MLAG ID on the *uplink switch*. """ - uplink_switch_port_channel_id = get(self.shared_utils.switch_data_combined, "uplink_switch_port_channel_id") + uplink_switch_port_channel_id = self.shared_utils.node_config.uplink_switch_port_channel_id if self.shared_utils.mlag_role == "secondary": # MLAG Secondary @@ -180,34 +180,34 @@ def _get_p2p_uplink(self: EosDesignsFacts, uplink_index: int, uplink_interface: if self.shared_utils.uplink_interface_speed is not None: uplink["speed"] = self.shared_utils.uplink_interface_speed - if self.shared_utils.uplink_bfd: + if self.shared_utils.node_config.uplink_bfd: uplink["bfd"] = True if self.shared_utils.uplink_switch_interface_speed is not None: uplink["peer_speed"] = self.shared_utils.uplink_switch_interface_speed - if self.shared_utils.uplink_ptp is not None: - uplink["ptp"] = self.shared_utils.uplink_ptp + if self.shared_utils.node_config.uplink_ptp: + uplink["ptp"] = {"enable": self.shared_utils.node_config.uplink_ptp.enable} elif self.shared_utils.ptp_enabled: uplink["ptp"] = {"enable": True} - if self.shared_utils.uplink_macsec is not None: - uplink["mac_security"] = self.shared_utils.uplink_macsec + if self.shared_utils.node_config.uplink_macsec.profile: + uplink["mac_security"] = {"profile": self.shared_utils.node_config.uplink_macsec.profile} if self.shared_utils.underlay_multicast is True and uplink_switch_facts.shared_utils.underlay_multicast is True: uplink["underlay_multicast"] = True - if self.shared_utils.underlay_rfc5549: + if self.inputs.underlay_rfc5549: uplink["ipv6_enable"] = True else: - uplink["prefix_length"] = self.shared_utils.fabric_ip_addressing_p2p_uplinks_ipv4_prefix_length + uplink["prefix_length"] = self.inputs.fabric_ip_addressing.p2p_uplinks.ipv4_prefix_length uplink["ip_address"] = self.shared_utils.ip_addressing.p2p_uplinks_ip(uplink_index) uplink["peer_ip_address"] = self.shared_utils.ip_addressing.p2p_uplinks_peer_ip(uplink_index) if self.shared_utils.link_tracking_groups is not None: uplink["link_tracking_groups"] = [{"name": lt_group["name"], "direction": "upstream"} for lt_group in self.shared_utils.link_tracking_groups] - if self.shared_utils.uplink_structured_config is not None: - uplink["structured_config"] = self.shared_utils.uplink_structured_config + if self.shared_utils.node_config.uplink_structured_config is not None: + uplink["structured_config"] = self.shared_utils.node_config.uplink_structured_config return uplink @@ -262,13 +262,13 @@ def _get_l2_uplink( if self.shared_utils.uplink_switch_interface_speed is not None: uplink["peer_speed"] = self.shared_utils.uplink_switch_interface_speed - if self.shared_utils.uplink_ptp is not None: - uplink["ptp"] = self.shared_utils.uplink_ptp + if self.shared_utils.node_config.uplink_ptp: + uplink["ptp"] = {"enable": self.shared_utils.node_config.uplink_ptp.enable} elif self.shared_utils.ptp_enabled: uplink["ptp"] = {"enable": True} # Remove vlans if upstream switch does not have them #} - if self.shared_utils.enable_trunk_groups: + if self.inputs.enable_trunk_groups: uplink["trunk_groups"] = ["UPLINK"] if self.shared_utils.mlag is True: uplink["peer_trunk_groups"] = [self.shared_utils.group] @@ -280,11 +280,11 @@ def _get_l2_uplink( if self.shared_utils.configure_inband_mgmt or self.shared_utils.configure_inband_mgmt_ipv6: # Always add inband_mgmt_vlan even if the uplink switch does not have this vlan defined - uplink_vlans.add(self.shared_utils.inband_mgmt_vlan) + uplink_vlans.add(self.shared_utils.node_config.inband_mgmt_vlan) uplink["vlans"] = list_compress(list(uplink_vlans)) if uplink_vlans else "none" - if uplink_native_vlan := get(self.shared_utils.switch_data_combined, "uplink_native_vlan"): + if uplink_native_vlan := self.shared_utils.node_config.uplink_native_vlan: uplink["native_vlan"] = uplink_native_vlan if self._short_esi is not None: @@ -297,8 +297,8 @@ def _get_l2_uplink( # This child device does not support VLANs, so we tell the peer to enable portfast uplink["peer_spanning_tree_portfast"] = "edge" - if self.shared_utils.uplink_structured_config is not None: - uplink["structured_config"] = self.shared_utils.uplink_structured_config + if self.shared_utils.node_config.uplink_structured_config is not None: + uplink["structured_config"] = self.shared_utils.node_config.uplink_structured_config return uplink @@ -310,31 +310,31 @@ def _get_p2p_vrfs_uplink(self: EosDesignsFacts, uplink_index: int, uplink_interf uplink = self._get_p2p_uplink(uplink_index, uplink_interface, uplink_switch, uplink_switch_interface) uplink["subinterfaces"] = [] for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: + for vrf in tenant.vrfs: # Only keep VRFs present on the uplink switch as well. # Also skip VRF default since it is covered on the parent interface. # ok to use like this because this is only ever called inside EosDesignsFacts uplink_switch_vrfs = uplink_switch_facts.shared_utils.vrfs - if vrf["name"] == "default" or vrf["name"] not in uplink_switch_vrfs: + if vrf.name == "default" or vrf.name not in uplink_switch_vrfs: continue vrf_id = self.shared_utils.get_vrf_id(vrf) subinterface = { "interface": f"{uplink_interface}.{vrf_id}", "peer_interface": f"{uplink_switch_interface}.{vrf_id}", - "vrf": vrf["name"], + "vrf": vrf.name, "encapsulation_dot1q_vlan": vrf_id, } - if self.shared_utils.underlay_rfc5549: + if self.inputs.underlay_rfc5549: subinterface["ipv6_enable"] = True else: - subinterface["prefix_length"] = self.shared_utils.fabric_ip_addressing_p2p_uplinks_ipv4_prefix_length - subinterface["ip_address"] = self.shared_utils.ip_addressing.p2p_vrfs_uplinks_ip(uplink_index, vrf["name"]) - subinterface["peer_ip_address"] = self.shared_utils.ip_addressing.p2p_vrfs_uplinks_peer_ip(uplink_index, vrf["name"]) + subinterface["prefix_length"] = self.inputs.fabric_ip_addressing.p2p_uplinks.ipv4_prefix_length + subinterface["ip_address"] = self.shared_utils.ip_addressing.p2p_vrfs_uplinks_ip(uplink_index, vrf.name) + subinterface["peer_ip_address"] = self.shared_utils.ip_addressing.p2p_vrfs_uplinks_peer_ip(uplink_index, vrf.name) - if self.shared_utils.uplink_structured_config is not None: - subinterface["structured_config"] = self.shared_utils.uplink_structured_config + if self.shared_utils.node_config.uplink_structured_config is not None: + subinterface["structured_config"] = self.shared_utils.node_config.uplink_structured_config append_if_not_duplicate( uplink["subinterfaces"], @@ -369,7 +369,7 @@ def _default_downlink_interfaces(self: EosDesignsFacts) -> list: Parsed by downstream switches during eos_designs_facts phase. """ - return range_expand(get(self.shared_utils.default_interfaces, "downlink_interfaces", default=[])) + return range_expand(self.shared_utils.default_interfaces.downlink_interfaces) @cached_property def uplink_switch_vrfs(self: EosDesignsFacts) -> list[str] | None: diff --git a/python-avd/pyavd/_eos_designs/eos_designs_facts/vlans.py b/python-avd/pyavd/_eos_designs/eos_designs_facts/vlans.py index ec5de1f9cd0..f3514f493c7 100644 --- a/python-avd/pyavd/_eos_designs/eos_designs_facts/vlans.py +++ b/python-avd/pyavd/_eos_designs/eos_designs_facts/vlans.py @@ -7,10 +7,11 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import get from pyavd.j2filters import list_compress, range_expand if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + from . import EosDesignsFacts @@ -36,34 +37,37 @@ def vlans(self: EosDesignsFacts) -> str: """ return list_compress(self._vlans) - def _parse_adapter_settings(self: EosDesignsFacts, adapter_settings: dict) -> tuple[set, set]: + def _parse_adapter_settings( + self: EosDesignsFacts, + adapter_settings: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem | EosDesigns.NetworkPortsItem, + ) -> tuple[set, set]: """Parse the given adapter_settings and return relevant vlans and trunk_groups.""" vlans = set() - trunk_groups = set(adapter_settings.get("trunk_groups", [])) - if "vlans" in adapter_settings and adapter_settings["vlans"] not in ["all", "", None]: - vlans.update(map(int, range_expand(str(adapter_settings["vlans"])))) - elif adapter_settings.get("mode", "") == "trunk" and not trunk_groups: + trunk_groups = set(adapter_settings.trunk_groups) + if adapter_settings.vlans not in ["all", "", None]: + vlans.update(map(int, range_expand(adapter_settings.vlans))) + elif adapter_settings.mode == "trunk" and not trunk_groups: # No vlans or trunk_groups defined, but this is a trunk, so default is all vlans allowed # No need to check further, since the list is now containing all vlans. return set(range(1, 4094)), trunk_groups - elif adapter_settings.get("mode", "") == "trunk phone": + elif adapter_settings.mode == "trunk phone": # # EOS default native VLAN is VLAN 1 - if "native_vlan" not in adapter_settings: + if not adapter_settings.native_vlan: vlans.add(1) else: # No vlans or mode defined so this is an access port with only vlan 1 allowed vlans.add(1) - if "native_vlan" in adapter_settings: - vlans.add(int(adapter_settings["native_vlan"])) - if "phone_vlan" in adapter_settings: - vlans.add(int(adapter_settings["phone_vlan"])) + if adapter_settings.native_vlan: + vlans.add(adapter_settings.native_vlan) + if adapter_settings.phone_vlan: + vlans.add(adapter_settings.phone_vlan) - for subinterface in get(adapter_settings, "port_channel.subinterfaces", default=[]): - if "vlan_id" in subinterface: - vlans.add(int(subinterface["vlan_id"])) - elif "number" in subinterface: - vlans.add(int(subinterface["number"])) + for subinterface in adapter_settings.port_channel.subinterfaces: + if subinterface.vlan_id: + vlans.add(subinterface.vlan_id) + elif subinterface.number: + vlans.add(subinterface.number) return vlans, trunk_groups @@ -72,7 +76,7 @@ def _local_endpoint_vlans_and_trunk_groups(self: EosDesignsFacts) -> tuple[set, """ Return list of vlans and list of trunk groups used by connected_endpoints on this switch. - Also includes the inband_mgmt_vlan + Also includes the inband_mgmt_vlan. """ if not (self.shared_utils.any_network_services and self.shared_utils.connected_endpoints): return set(), set() @@ -81,15 +85,14 @@ def _local_endpoint_vlans_and_trunk_groups(self: EosDesignsFacts) -> tuple[set, trunk_groups = set() if self.shared_utils.configure_inband_mgmt: - vlans.add(self.shared_utils.inband_mgmt_vlan) + vlans.add(self.shared_utils.node_config.inband_mgmt_vlan) - for connected_endpoints_key in self.shared_utils.connected_endpoints_keys: - connected_endpoints = get(self._hostvars, connected_endpoints_key["key"], default=[]) - for connected_endpoint in connected_endpoints: - for index, adapter in enumerate(connected_endpoint.get("adapters", [])): - adapter["context"] = f"{connected_endpoints_key['key']}[name={connected_endpoint['name']}].adapters[{index}]" + for connected_endpoints_key in self.inputs._dynamic_keys.connected_endpoints: + for connected_endpoint in connected_endpoints_key.value: + for index, adapter in enumerate(connected_endpoint.adapters): + adapter._context = f"{connected_endpoints_key.key}[name={connected_endpoint.name}].adapters[{index}]" adapter_settings = self.shared_utils.get_merged_adapter_settings(adapter) - if self.shared_utils.hostname not in adapter_settings.get("switches", []): + if self.shared_utils.hostname not in adapter_settings.switches: # This switch is not connected to this endpoint. Skipping. continue @@ -102,9 +105,8 @@ def _local_endpoint_vlans_and_trunk_groups(self: EosDesignsFacts) -> tuple[set, # configure all vlans anyway. return vlans, trunk_groups - network_ports = get(self._hostvars, "network_ports", default=[]) - for index, network_port_item in enumerate(network_ports): - for switch_regex in network_port_item.get("switches", []): + for index, network_port_item in enumerate(self.inputs.network_ports): + for switch_regex in network_port_item.switches: # The match test is built on Python re.match which tests from the beginning of the string #} # Since the user would not expect "DC1-LEAF1" to also match "DC-LEAF11" we will force ^ and $ around the regex raw_switch_regex = rf"^{switch_regex}$" @@ -112,7 +114,7 @@ def _local_endpoint_vlans_and_trunk_groups(self: EosDesignsFacts) -> tuple[set, # Skip entry if no match continue - network_port_item["context"] = f"network_ports[{index}]" + network_port_item._context = f"network_ports[{index}]" adapter_settings = self.shared_utils.get_merged_adapter_settings(network_port_item) adapter_vlans, adapter_trunk_groups = self._parse_adapter_settings(adapter_settings) vlans.update(adapter_vlans) @@ -179,7 +181,7 @@ def _endpoint_vlans(self: EosDesignsFacts) -> set[int]: Ex: {1, 20, 21, 22, 23} or set(). """ - if not self.shared_utils.filter_only_vlans_in_use: + if not self.shared_utils.node_config.filter.only_vlans_in_use: return set() endpoint_vlans, _ = self._endpoint_vlans_and_trunk_groups @@ -197,7 +199,7 @@ def endpoint_vlans(self: EosDesignsFacts) -> str | None: Ex: "1,20-30" or "". """ - if self.shared_utils.filter_only_vlans_in_use: + if self.shared_utils.node_config.filter.only_vlans_in_use: return list_compress(list(self._endpoint_vlans)) return None @@ -205,7 +207,7 @@ def endpoint_vlans(self: EosDesignsFacts) -> str | None: @cached_property def _endpoint_trunk_groups(self: EosDesignsFacts) -> set[str]: """Return set of trunk_groups in use by endpoints connected to this switch, downstream switches or MLAG peer.""" - if not self.shared_utils.filter_only_vlans_in_use: + if not self.shared_utils.node_config.filter.only_vlans_in_use: return set() _, endpoint_trunk_groups = self._endpoint_vlans_and_trunk_groups @@ -251,61 +253,48 @@ def _vlans(self: EosDesignsFacts) -> list[int]: vlans = [] match_tags = self.shared_utils.filter_tags - if self.shared_utils.filter_only_vlans_in_use: + if self.shared_utils.node_config.filter.only_vlans_in_use: # Only include the vlans that are used by connected endpoints endpoint_trunk_groups = self._endpoint_trunk_groups endpoint_vlans = self._endpoint_vlans - for network_services_key in self.shared_utils.network_services_keys: - tenants = get(self._hostvars, network_services_key["name"], default=[]) + for network_services_key in self.inputs._dynamic_keys.network_services: + tenants = network_services_key.value for tenant in tenants: - if not set(self.shared_utils.filter_tenants).intersection([tenant["name"], "all"]): + if not set(self.shared_utils.node_config.filter.tenants).intersection([tenant.name, "all"]): # Not matching tenant filters. Skipping this tenant. continue - vrfs = tenant.get("vrfs", []) - for vrf in vrfs: - svis = vrf.get("svis", []) - for svi in svis: - svi_tags = svi.get("tags", ["all"]) - if "all" in match_tags or set(svi_tags).intersection(match_tags): - if self.shared_utils.filter_only_vlans_in_use: + for vrf in tenant.vrfs: + for svi in vrf.svis: + if "all" in match_tags or set(svi.tags).intersection(match_tags): + if self.shared_utils.node_config.filter.only_vlans_in_use: # Check if vlan is in use - if int(svi["id"]) in endpoint_vlans: - vlans.append(int(svi["id"])) + if svi.id in endpoint_vlans: + vlans.append(svi.id) continue # Check if vlan has a trunk group defined which is in use - if ( - self.shared_utils.enable_trunk_groups - and svi.get("trunk_groups") - and endpoint_trunk_groups.intersection(svi["trunk_groups"]) - ): - vlans.append(int(svi["id"])) + if self.inputs.enable_trunk_groups and svi.trunk_groups and endpoint_trunk_groups.intersection(svi.trunk_groups): + vlans.append(svi.id) continue # Skip since the vlan is not in use continue - vlans.append(int(svi["id"])) + vlans.append(svi.id) - l2vlans = tenant.get("l2vlans", []) - for l2vlan in l2vlans: - l2vlan_tags = l2vlan.get("tags", ["all"]) - if "all" in match_tags or set(l2vlan_tags).intersection(match_tags): - if self.shared_utils.filter_only_vlans_in_use: + for l2vlan in tenant.l2vlans: + if "all" in match_tags or set(l2vlan.tags).intersection(match_tags): + if self.shared_utils.node_config.filter.only_vlans_in_use: # Check if vlan is in use - if int(l2vlan["id"]) in endpoint_vlans: - vlans.append(int(l2vlan["id"])) + if l2vlan.id in endpoint_vlans: + vlans.append(l2vlan.id) continue # Check if vlan has a trunk group defined which is in use - if ( - self.shared_utils.enable_trunk_groups - and l2vlan.get("trunk_groups") - and endpoint_trunk_groups.intersection(l2vlan["trunk_groups"]) - ): - vlans.append(int(l2vlan["id"])) + if self.inputs.enable_trunk_groups and l2vlan.trunk_groups and endpoint_trunk_groups.intersection(l2vlan.trunk_groups): + vlans.append(l2vlan.id) continue # Skip since the vlan is not in use continue - vlans.append(int(l2vlan["id"])) + vlans.append(l2vlan.id) return vlans return [] diff --git a/python-avd/pyavd/_eos_designs/eos_designs_facts/wan.py b/python-avd/pyavd/_eos_designs/eos_designs_facts/wan.py index ad5c2ef2664..cf969878e29 100644 --- a/python-avd/pyavd/_eos_designs/eos_designs_facts/wan.py +++ b/python-avd/pyavd/_eos_designs/eos_designs_facts/wan.py @@ -31,4 +31,8 @@ def wan_path_groups(self: EosDesignsFacts) -> list | None: if not self.shared_utils.is_wan_router: return None - return self.shared_utils.wan_local_path_groups + wan_path_groups = self.shared_utils.wan_local_path_groups._as_list() + for wan_path_group in wan_path_groups: + wan_path_group["_interfaces"] = self.shared_utils.wan_local_path_groups[wan_path_group["name"]]._interfaces + + return wan_path_groups diff --git a/python-avd/pyavd/_eos_designs/schema/__init__.py b/python-avd/pyavd/_eos_designs/schema/__init__.py new file mode 100644 index 00000000000..afa5548636b --- /dev/null +++ b/python-avd/pyavd/_eos_designs/schema/__init__.py @@ -0,0 +1,57543 @@ +# Copyright (c) 2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, ClassVar, Literal + +from pyavd._eos_cli_config_gen.schema import EosCliConfigGen +from pyavd._schema.coerce_type import coerce_type +from pyavd._schema.models.avd_indexed_list import AvdIndexedList +from pyavd._schema.models.avd_list import AvdList +from pyavd._schema.models.avd_model import AvdModel +from pyavd._schema.models.eos_designs_root_model import EosDesignsRootModel + +if TYPE_CHECKING: + from pyavd._utils import Undefined, UndefinedType + + +class EosDesigns(EosDesignsRootModel): + """Subclass of AvdModel.""" + + class ApplicationClassification(EosCliConfigGen.ApplicationTrafficRecognition): + """Subclass of AvdModel.""" + + class BfdMultihop(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interval": {"type": int}, "min_rx": {"type": int}, "multiplier": {"type": int}, "_custom_data": {"type": dict}} + interval: int + min_rx: int + multiplier: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | UndefinedType = Undefined, + min_rx: int | UndefinedType = Undefined, + multiplier: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BfdMultihop. + + + Subclass of AvdModel. + + Args: + interval: interval + min_rx: min_rx + multiplier: multiplier + _custom_data: _custom_data + + """ + + class BgpDistance(EosCliConfigGen.RouterBgp.Distance): + """Subclass of AvdModel.""" + + class BgpGracefulRestart(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool, "default": False}, "restart_time": {"type": int, "default": 300}, "_custom_data": {"type": dict}} + enabled: bool + """ + Enable or disable graceful-restart for all BGP peers. + + Default value: `False` + """ + restart_time: int + """ + Restart time in seconds. + + Default value: `300` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + restart_time: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BgpGracefulRestart. + + + Subclass of AvdModel. + + Args: + enabled: Enable or disable graceful-restart for all BGP peers. + restart_time: Restart time in seconds. + _custom_data: _custom_data + + """ + + class BgpPeerGroups(AvdModel): + """Subclass of AvdModel.""" + + class Ipv4UnderlayPeers(AvdModel): + """Subclass of AvdModel.""" + + class StructuredConfig(EosCliConfigGen.RouterBgp.PeerGroupsItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str, "default": "IPv4-UNDERLAY-PEERS"}, + "password": {"type": str}, + "bfd": {"type": bool, "default": False}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + name: str + """ + Name of peer group. + + Default value: `"IPv4-UNDERLAY-PEERS"` + """ + password: str | None + """Type 7 encrypted password.""" + bfd: bool + """Default value: `False`""" + structured_config: StructuredConfig + """ + Custom structured config added under router_bgp.peer_groups.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + password: str | None | UndefinedType = Undefined, + bfd: bool | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4UnderlayPeers. + + + Subclass of AvdModel. + + Args: + name: Name of peer group. + password: Type 7 encrypted password. + bfd: bfd + structured_config: + Custom structured config added under router_bgp.peer_groups.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MlagIpv4UnderlayPeer(AvdModel): + """Subclass of AvdModel.""" + + class StructuredConfig(EosCliConfigGen.RouterBgp.PeerGroupsItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str, "default": "MLAG-IPv4-UNDERLAY-PEER"}, + "password": {"type": str}, + "bfd": {"type": bool, "default": False}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + name: str + """ + Name of peer group. + + Default value: `"MLAG-IPv4-UNDERLAY-PEER"` + """ + password: str | None + """Type 7 encrypted password.""" + bfd: bool + """Default value: `False`""" + structured_config: StructuredConfig + """ + Custom structured config added under router_bgp.peer_groups.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + password: str | None | UndefinedType = Undefined, + bfd: bool | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MlagIpv4UnderlayPeer. + + + Subclass of AvdModel. + + Args: + name: Name of peer group. + password: Type 7 encrypted password. + bfd: bfd + structured_config: + Custom structured config added under router_bgp.peer_groups.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class EvpnOverlayPeers(AvdModel): + """Subclass of AvdModel.""" + + class StructuredConfig(EosCliConfigGen.RouterBgp.PeerGroupsItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str, "default": "EVPN-OVERLAY-PEERS"}, + "password": {"type": str}, + "bfd": {"type": bool, "default": True}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + name: str + """ + Name of peer group. + + Default value: `"EVPN-OVERLAY-PEERS"` + """ + password: str | None + """Type 7 encrypted password.""" + bfd: bool + """Default value: `True`""" + structured_config: StructuredConfig + """ + Custom structured config added under router_bgp.peer_groups.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + password: str | None | UndefinedType = Undefined, + bfd: bool | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnOverlayPeers. + + + Subclass of AvdModel. + + Args: + name: Name of peer group. + password: Type 7 encrypted password. + bfd: bfd + structured_config: + Custom structured config added under router_bgp.peer_groups.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class EvpnOverlayCore(AvdModel): + """Subclass of AvdModel.""" + + class StructuredConfig(EosCliConfigGen.RouterBgp.PeerGroupsItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str, "default": "EVPN-OVERLAY-CORE"}, + "password": {"type": str}, + "bfd": {"type": bool, "default": True}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + name: str + """ + Name of peer group. + + Default value: `"EVPN-OVERLAY-CORE"` + """ + password: str | None + """Type 7 encrypted password.""" + bfd: bool + """Default value: `True`""" + structured_config: StructuredConfig + """ + Custom structured config added under router_bgp.peer_groups.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + password: str | None | UndefinedType = Undefined, + bfd: bool | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnOverlayCore. + + + Subclass of AvdModel. + + Args: + name: Name of peer group. + password: Type 7 encrypted password. + bfd: bfd + structured_config: + Custom structured config added under router_bgp.peer_groups.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MplsOverlayPeers(AvdModel): + """Subclass of AvdModel.""" + + class StructuredConfig(EosCliConfigGen.RouterBgp.PeerGroupsItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str, "default": "MPLS-OVERLAY-PEERS"}, + "password": {"type": str}, + "bfd": {"type": bool, "default": True}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + name: str + """ + Name of peer group. + + Default value: `"MPLS-OVERLAY-PEERS"` + """ + password: str | None + """Type 7 encrypted password.""" + bfd: bool + """Default value: `True`""" + structured_config: StructuredConfig + """ + Custom structured config added under router_bgp.peer_groups.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + password: str | None | UndefinedType = Undefined, + bfd: bool | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MplsOverlayPeers. + + + Subclass of AvdModel. + + Args: + name: Name of peer group. + password: Type 7 encrypted password. + bfd: bfd + structured_config: + Custom structured config added under router_bgp.peer_groups.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class RrOverlayPeers(AvdModel): + """Subclass of AvdModel.""" + + class StructuredConfig(EosCliConfigGen.RouterBgp.PeerGroupsItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str, "default": "RR-OVERLAY-PEERS"}, + "password": {"type": str}, + "bfd": {"type": bool, "default": True}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + name: str + """ + Name of peer group. + + Default value: `"RR-OVERLAY-PEERS"` + """ + password: str | None + """Type 7 encrypted password.""" + bfd: bool + """Default value: `True`""" + structured_config: StructuredConfig + """ + Custom structured config added under router_bgp.peer_groups.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + password: str | None | UndefinedType = Undefined, + bfd: bool | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RrOverlayPeers. + + + Subclass of AvdModel. + + Args: + name: Name of peer group. + password: Type 7 encrypted password. + bfd: bfd + structured_config: + Custom structured config added under router_bgp.peer_groups.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class IpvpnGatewayPeers(AvdModel): + """Subclass of AvdModel.""" + + class StructuredConfig(EosCliConfigGen.RouterBgp.PeerGroupsItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str, "default": "IPVPN-GATEWAY-PEERS"}, + "password": {"type": str}, + "bfd": {"type": bool, "default": True}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + name: str + """ + Name of peer group. + + Default value: `"IPVPN-GATEWAY-PEERS"` + """ + password: str | None + """Type 7 encrypted password.""" + bfd: bool + """Default value: `True`""" + structured_config: StructuredConfig + """ + Custom structured config added under router_bgp.peer_groups.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + password: str | None | UndefinedType = Undefined, + bfd: bool | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpvpnGatewayPeers. + + + Subclass of AvdModel. + + Args: + name: Name of peer group. + password: Type 7 encrypted password. + bfd: bfd + structured_config: + Custom structured config added under router_bgp.peer_groups.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class WanOverlayPeers(AvdModel): + """Subclass of AvdModel.""" + + class BfdTimers(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "interval": {"type": int, "default": 1000}, + "min_rx": {"type": int, "default": 1000}, + "multiplier": {"type": int, "default": 10}, + "_custom_data": {"type": dict}, + } + interval: int + """ + Interval in milliseconds. + + Default value: `1000` + """ + min_rx: int + """ + Rate in milliseconds. + + Default value: `1000` + """ + multiplier: int + """Default value: `10`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | UndefinedType = Undefined, + min_rx: int | UndefinedType = Undefined, + multiplier: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BfdTimers. + + + Subclass of AvdModel. + + Args: + interval: Interval in milliseconds. + min_rx: Rate in milliseconds. + multiplier: multiplier + _custom_data: _custom_data + + """ + + class ListenRangePrefixes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + ListenRangePrefixes._item_type = str + + class StructuredConfig(EosCliConfigGen.RouterBgp.PeerGroupsItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str, "default": "WAN-OVERLAY-PEERS"}, + "password": {"type": str}, + "bfd": {"type": bool, "default": True}, + "bfd_timers": {"type": BfdTimers}, + "listen_range_prefixes": {"type": ListenRangePrefixes}, + "ttl_maximum_hops": {"type": int, "default": 1}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + name: str + """ + Name of peer group. + + Default value: `"WAN-OVERLAY-PEERS"` + """ + password: str | None + """ + Type 7 encrypted password. + When configuring a password on the `wan_overlay_peers` BGP peer group, + it + may also be required to set a password for the `wan_rr_overlay_peers` BGP peer group. + This is + required in the case where one or more pathfinders use the same VTEP IP range as the edge routers. + If the password is not set, the static BGP peerings between Pathfinders may not come up. + """ + bfd: bool + """Default value: `True`""" + bfd_timers: BfdTimers + """ + Specify the BFD timers to override the default values. + It is recommended to keep BFD total timeout + longer than the DPS timeout. + The Default BFD timeout is 10 x 1 seconds and the default DPS timeout + is 5 x 1 seconds. + + Subclass of AvdModel. + """ + listen_range_prefixes: ListenRangePrefixes + """ + Only used for nodes where `wan_role` is `server` like AutoVPN RRs and Pathfinders. + For clients, AVD + will raise an error if the Loopback0 IP is not in any listen range. + + Subclass of AvdList with `str` + items. + """ + ttl_maximum_hops: int + """Default value: `1`""" + structured_config: StructuredConfig + """ + Custom structured config added under router_bgp.peer_groups.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + password: str | None | UndefinedType = Undefined, + bfd: bool | UndefinedType = Undefined, + bfd_timers: BfdTimers | UndefinedType = Undefined, + listen_range_prefixes: ListenRangePrefixes | UndefinedType = Undefined, + ttl_maximum_hops: int | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + WanOverlayPeers. + + + Subclass of AvdModel. + + Args: + name: Name of peer group. + password: + Type 7 encrypted password. + When configuring a password on the `wan_overlay_peers` BGP peer group, + it + may also be required to set a password for the `wan_rr_overlay_peers` BGP peer group. + This is + required in the case where one or more pathfinders use the same VTEP IP range as the edge routers. + If the password is not set, the static BGP peerings between Pathfinders may not come up. + bfd: bfd + bfd_timers: + Specify the BFD timers to override the default values. + It is recommended to keep BFD total timeout + longer than the DPS timeout. + The Default BFD timeout is 10 x 1 seconds and the default DPS timeout + is 5 x 1 seconds. + + Subclass of AvdModel. + listen_range_prefixes: + Only used for nodes where `wan_role` is `server` like AutoVPN RRs and Pathfinders. + For clients, AVD + will raise an error if the Loopback0 IP is not in any listen range. + + Subclass of AvdList with `str` + items. + ttl_maximum_hops: ttl_maximum_hops + structured_config: + Custom structured config added under router_bgp.peer_groups.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class WanRrOverlayPeers(AvdModel): + """Subclass of AvdModel.""" + + class BfdTimers(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "interval": {"type": int, "default": 1000}, + "min_rx": {"type": int, "default": 1000}, + "multiplier": {"type": int, "default": 10}, + "_custom_data": {"type": dict}, + } + interval: int + """ + Interval in milliseconds. + + Default value: `1000` + """ + min_rx: int + """ + Rate in milliseconds. + + Default value: `1000` + """ + multiplier: int + """Default value: `10`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | UndefinedType = Undefined, + min_rx: int | UndefinedType = Undefined, + multiplier: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BfdTimers. + + + Subclass of AvdModel. + + Args: + interval: Interval in milliseconds. + min_rx: Rate in milliseconds. + multiplier: multiplier + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen.RouterBgp.PeerGroupsItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str, "default": "WAN-RR-OVERLAY-PEERS"}, + "password": {"type": str}, + "bfd": {"type": bool, "default": True}, + "bfd_timers": {"type": BfdTimers}, + "ttl_maximum_hops": {"type": int, "default": 1}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + name: str + """ + Name of peer group. + + Default value: `"WAN-RR-OVERLAY-PEERS"` + """ + password: str | None + """ + Type 7 encrypted password. + When configuring a password on the `wan_overlay_peers` BGP peer group, + it + may also be required to set a password for the `wan_rr_overlay_peers` BGP peer group. + This is + required in the case where one or more pathfinders use the same VTEP IP range as the edge routers. + If the password is not set, the static BGP peerings between Pathfinders may not come up. + """ + bfd: bool + """Default value: `True`""" + bfd_timers: BfdTimers + """ + Specify the BFD timers to override the default values. + It is recommended to keep BFD total timeout + longer than the DPS timeout. + The Default BFD timeout is 10 x 1 seconds and the default DPS timeout + is 5 x 1 seconds. + + Subclass of AvdModel. + """ + ttl_maximum_hops: int + """Default value: `1`""" + structured_config: StructuredConfig + """ + Custom structured config added under router_bgp.peer_groups.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + password: str | None | UndefinedType = Undefined, + bfd: bool | UndefinedType = Undefined, + bfd_timers: BfdTimers | UndefinedType = Undefined, + ttl_maximum_hops: int | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + WanRrOverlayPeers. + + + Subclass of AvdModel. + + Args: + name: Name of peer group. + password: + Type 7 encrypted password. + When configuring a password on the `wan_overlay_peers` BGP peer group, + it + may also be required to set a password for the `wan_rr_overlay_peers` BGP peer group. + This is + required in the case where one or more pathfinders use the same VTEP IP range as the edge routers. + If the password is not set, the static BGP peerings between Pathfinders may not come up. + bfd: bfd + bfd_timers: + Specify the BFD timers to override the default values. + It is recommended to keep BFD total timeout + longer than the DPS timeout. + The Default BFD timeout is 10 x 1 seconds and the default DPS timeout + is 5 x 1 seconds. + + Subclass of AvdModel. + ttl_maximum_hops: ttl_maximum_hops + structured_config: + Custom structured config added under router_bgp.peer_groups.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ipv4_underlay_peers": {"type": Ipv4UnderlayPeers}, + "mlag_ipv4_underlay_peer": {"type": MlagIpv4UnderlayPeer}, + "evpn_overlay_peers": {"type": EvpnOverlayPeers}, + "evpn_overlay_core": {"type": EvpnOverlayCore}, + "mpls_overlay_peers": {"type": MplsOverlayPeers}, + "rr_overlay_peers": {"type": RrOverlayPeers}, + "ipvpn_gateway_peers": {"type": IpvpnGatewayPeers}, + "wan_overlay_peers": {"type": WanOverlayPeers}, + "wan_rr_overlay_peers": {"type": WanRrOverlayPeers}, + "_custom_data": {"type": dict}, + } + ipv4_underlay_peers: Ipv4UnderlayPeers + """Subclass of AvdModel.""" + mlag_ipv4_underlay_peer: MlagIpv4UnderlayPeer + """Subclass of AvdModel.""" + evpn_overlay_peers: EvpnOverlayPeers + """Subclass of AvdModel.""" + evpn_overlay_core: EvpnOverlayCore + """Subclass of AvdModel.""" + mpls_overlay_peers: MplsOverlayPeers + """Subclass of AvdModel.""" + rr_overlay_peers: RrOverlayPeers + """Subclass of AvdModel.""" + ipvpn_gateway_peers: IpvpnGatewayPeers + """Subclass of AvdModel.""" + wan_overlay_peers: WanOverlayPeers + """Subclass of AvdModel.""" + wan_rr_overlay_peers: WanRrOverlayPeers + """ + Configuration options for the peer-group created to peer between AutoVPN RRs or CV Pathfinders. + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4_underlay_peers: Ipv4UnderlayPeers | UndefinedType = Undefined, + mlag_ipv4_underlay_peer: MlagIpv4UnderlayPeer | UndefinedType = Undefined, + evpn_overlay_peers: EvpnOverlayPeers | UndefinedType = Undefined, + evpn_overlay_core: EvpnOverlayCore | UndefinedType = Undefined, + mpls_overlay_peers: MplsOverlayPeers | UndefinedType = Undefined, + rr_overlay_peers: RrOverlayPeers | UndefinedType = Undefined, + ipvpn_gateway_peers: IpvpnGatewayPeers | UndefinedType = Undefined, + wan_overlay_peers: WanOverlayPeers | UndefinedType = Undefined, + wan_rr_overlay_peers: WanRrOverlayPeers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BgpPeerGroups. + + + Subclass of AvdModel. + + Args: + ipv4_underlay_peers: Subclass of AvdModel. + mlag_ipv4_underlay_peer: Subclass of AvdModel. + evpn_overlay_peers: Subclass of AvdModel. + evpn_overlay_core: Subclass of AvdModel. + mpls_overlay_peers: Subclass of AvdModel. + rr_overlay_peers: Subclass of AvdModel. + ipvpn_gateway_peers: Subclass of AvdModel. + wan_overlay_peers: Subclass of AvdModel. + wan_rr_overlay_peers: + Configuration options for the peer-group created to peer between AutoVPN RRs or CV Pathfinders. + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class ConnectedEndpointsKeysItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"key": {"type": str}, "type": {"type": str}, "description": {"type": str}, "_custom_data": {"type": dict}} + key: str + type: str | None + """Type used for documentation.""" + description: str | None + """Description used for documentation.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + key: str | UndefinedType = Undefined, + type: str | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ConnectedEndpointsKeysItem. + + + Subclass of AvdModel. + + Args: + key: key + type: Type used for documentation. + description: Description used for documentation. + _custom_data: _custom_data + + """ + + class ConnectedEndpointsKeys(AvdIndexedList[str, ConnectedEndpointsKeysItem]): + """Subclass of AvdIndexedList with `ConnectedEndpointsKeysItem` items. Primary key is `key` (`str`).""" + + _primary_key: ClassVar[str] = "key" + + ConnectedEndpointsKeys._item_type = ConnectedEndpointsKeysItem + + class CoreInterfaces(AvdModel): + """Subclass of AvdModel.""" + + class P2pLinksIpPoolsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "ipv4_pool": {"type": str}, + "prefix_size": {"type": int, "default": 31}, + "_custom_data": {"type": dict}, + } + name: str + """P2P pool name.""" + ipv4_pool: str | None + """IPv4 address/Mask.""" + prefix_size: int + """ + Subnet mask size. + + Default value: `31` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + ipv4_pool: str | None | UndefinedType = Undefined, + prefix_size: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + P2pLinksIpPoolsItem. + + + Subclass of AvdModel. + + Args: + name: P2P pool name. + ipv4_pool: IPv4 address/Mask. + prefix_size: Subnet mask size. + _custom_data: _custom_data + + """ + + class P2pLinksIpPools(AvdIndexedList[str, P2pLinksIpPoolsItem]): + """Subclass of AvdIndexedList with `P2pLinksIpPoolsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + P2pLinksIpPools._item_type = P2pLinksIpPoolsItem + + class P2pLinksProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class Ip(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Ip._item_type = str + + class Nodes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Nodes._item_type = str + + class Interfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Interfaces._item_type = str + + class As(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + As._item_type = str + + class Descriptions(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Descriptions._item_type = str + + class Ptp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enabled: bool + """ + Enable PTP. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, enabled: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Ptp. + + + Subclass of AvdModel. + + Args: + enabled: Enable PTP. + _custom_data: _custom_data + + """ + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class PortChannel(AvdModel): + """Subclass of AvdModel.""" + + class NodesChildInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Interfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Interfaces._item_type = str + + _fields: ClassVar[dict] = { + "node": {"type": str}, + "interfaces": {"type": Interfaces}, + "channel_id": {"type": int}, + "_custom_data": {"type": dict}, + } + node: str + interfaces: Interfaces + """ + List of node interfaces. Ex.- [ 'node1 interface1', 'node1 interface2' ]. + + Subclass of AvdList with + `str` items. + """ + channel_id: int | None + """ + Port-Channel ID. If no channel_id is specified, an id is generated from the first switch port in the + port channel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + node: str | UndefinedType = Undefined, + interfaces: Interfaces | UndefinedType = Undefined, + channel_id: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NodesChildInterfacesItem. + + + Subclass of AvdModel. + + Args: + node: node + interfaces: + List of node interfaces. Ex.- [ 'node1 interface1', 'node1 interface2' ]. + + Subclass of AvdList with + `str` items. + channel_id: + Port-Channel ID. If no channel_id is specified, an id is generated from the first switch port in the + port channel. + _custom_data: _custom_data + + """ + + class NodesChildInterfaces(AvdIndexedList[str, NodesChildInterfacesItem]): + """Subclass of AvdIndexedList with `NodesChildInterfacesItem` items. Primary key is `node` (`str`).""" + + _primary_key: ClassVar[str] = "node" + + NodesChildInterfaces._item_type = NodesChildInterfacesItem + + _fields: ClassVar[dict] = { + "description": {"type": str}, + "mode": {"type": str, "default": "active"}, + "nodes_child_interfaces": {"type": NodesChildInterfaces}, + "_custom_data": {"type": dict}, + } + description: str | None + """ + Description or description template to be used on the port-channel interface. + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `peer`: The name of the peer. + - `interface`: The local port-channel interface name. + - + `peer_interface`: The port-channel interface on the peer. + - `port_channel_id`: The local port- + channel ID. + - `peer_port_channel_id`: The ID of the port-channel on the peer. + + Falls back to the + description on the `p2p_link` if set. Otherwise default description is set by + `default_underlay_p2p_port_channel_description`. + By default the description is templated from the + name and port_channel interface of the peer. + """ + mode: str + """Default value: `"active"`""" + nodes_child_interfaces: NodesChildInterfaces + """Subclass of AvdIndexedList with `NodesChildInterfacesItem` items. Primary key is `node` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + description: str | None | UndefinedType = Undefined, + mode: str | UndefinedType = Undefined, + nodes_child_interfaces: NodesChildInterfaces | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PortChannel. + + + Subclass of AvdModel. + + Args: + description: + Description or description template to be used on the port-channel interface. + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `peer`: The name of the peer. + - `interface`: The local port-channel interface name. + - + `peer_interface`: The port-channel interface on the peer. + - `port_channel_id`: The local port- + channel ID. + - `peer_port_channel_id`: The ID of the port-channel on the peer. + + Falls back to the + description on the `p2p_link` if set. Otherwise default description is set by + `default_underlay_p2p_port_channel_description`. + By default the description is templated from the + name and port_channel interface of the peer. + mode: mode + nodes_child_interfaces: Subclass of AvdIndexedList with `NodesChildInterfacesItem` items. Primary key is `node` (`str`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "id": {"type": int}, + "speed": {"type": str}, + "ip_pool": {"type": str}, + "subnet": {"type": str}, + "ip": {"type": Ip}, + "ipv6_enable": {"type": bool, "default": False}, + "nodes": {"type": Nodes}, + "interfaces": {"type": Interfaces}, + "field_as": {"type": As}, + "descriptions": {"type": Descriptions}, + "include_in_underlay_protocol": {"type": bool, "default": True}, + "isis_hello_padding": {"type": bool, "default": True}, + "isis_metric": {"type": int}, + "isis_circuit_type": {"type": str}, + "isis_authentication_mode": {"type": str}, + "isis_authentication_key": {"type": str}, + "isis_network_type": {"type": str, "default": "point-to-point"}, + "mpls_ip": {"type": bool}, + "mpls_ldp": {"type": bool}, + "mtu": {"type": int}, + "bfd": {"type": bool}, + "ptp": {"type": Ptp}, + "sflow": {"type": bool}, + "underlay_multicast": {"type": bool, "default": False}, + "flow_tracking": {"type": FlowTracking}, + "qos_profile": {"type": str}, + "macsec_profile": {"type": str}, + "port_channel": {"type": PortChannel}, + "raw_eos_cli": {"type": str}, + "routing_protocol": {"type": str}, + "structured_config": {"type": dict}, + "_custom_data": {"type": dict}, + } + _field_to_key_map: ClassVar[dict] = {"field_as": "as"} + _key_to_field_map: ClassVar[dict] = {"as": "field_as"} + name: str + """P2P profile name. Any variable supported under `p2p_links` can be inherited from a profile.""" + id: int | None + """ + Unique id per subnet_summary. Used to calculate ip addresses. + Required with ip_pool. ID starting + from 1. + """ + speed: str | None + """ + Speed should be set in the format `` or `forced ` or `auto + `. + """ + ip_pool: str | None + """ + P2P pool name. IP Pool defined under p2p_links_ip_pools. A /31 will be taken from the pool per P2P + link. + """ + subnet: str | None + """IPv4 address/Mask. Subnet used on this P2P link.""" + ip: Ip + """ + Specific IP addresses used on this P2P link. + + Subclass of AvdList with `str` items. + """ + ipv6_enable: bool + """ + Allows turning on ipv6 for the link or profile (also autodetected based on underlay_rfc5549 and + include_in_underlay_protocol). + + Default value: `False` + """ + nodes: Nodes + """ + Nodes where this link should be configured. + + Subclass of AvdList with `str` items. + """ + interfaces: Interfaces + """ + Interfaces where this link should be configured and Required unless using port-channels. + + Subclass + of AvdList with `str` items. + """ + field_as: As + """ + AS numbers for BGP. + Required with bgp peering. + + + Subclass of AvdList with `str` items. + """ + descriptions: Descriptions + """ + Interface descriptions. + + Subclass of AvdList with `str` items. + """ + include_in_underlay_protocol: bool + """ + Add this interface to underlay routing protocol. + + Default value: `True` + """ + isis_hello_padding: bool + """Default value: `True`""" + isis_metric: int | None + isis_circuit_type: Literal["level-1", "level-2", "level-1-2"] | None + isis_authentication_mode: Literal["md5", "text"] | None + isis_authentication_key: str | None + """Type-7 encrypted password.""" + isis_network_type: Literal["point-to-point", "broadcast"] + """Default value: `"point-to-point"`""" + mpls_ip: bool | None + """MPLS parameters. Default value is true if switch.mpls_lsr is true.""" + mpls_ldp: bool | None + """MPLS parameters. Default value is true for ldp underlay variants, otherwise false.""" + mtu: int | None + """MTU for this P2P link. Default value same as p2p_uplinks_mtu.""" + bfd: bool | None + """Enable BFD (only considered for BGP).""" + ptp: Ptp + """ + PTP parameters. + + Subclass of AvdModel. + """ + sflow: bool | None + """Enable sFlow. Overrides `fabric_sflow` setting.""" + underlay_multicast: bool + """ + Enable PIM sparse mode. Requires `include_in_underlay_protocol` and the global `underlay_multicast` + to be `true`. + + Default value: `False` + """ + flow_tracking: FlowTracking + """ + Enable flow-tracking. Overrides `fabric_flow_tracking` setting. + + Subclass of AvdModel. + """ + qos_profile: str | None + """QOS service profile.""" + macsec_profile: str | None + """MAC security profile.""" + port_channel: PortChannel + """ + Port-channel parameters. + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the point-to-point interface in the final EOS configuration.""" + routing_protocol: Literal["ebgp"] | None + """ + Enables deviation of the routing protocol used on this link from the fabric underlay default. + - + ebgp: Enforce plain IPv4 BGP peering + """ + structured_config: dict + """ + Custom structured config for interfaces. + Note! The content of this dictionary is _not_ validated by + the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + id: int | None | UndefinedType = Undefined, + speed: str | None | UndefinedType = Undefined, + ip_pool: str | None | UndefinedType = Undefined, + subnet: str | None | UndefinedType = Undefined, + ip: Ip | UndefinedType = Undefined, + ipv6_enable: bool | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + interfaces: Interfaces | UndefinedType = Undefined, + field_as: As | UndefinedType = Undefined, + descriptions: Descriptions | UndefinedType = Undefined, + include_in_underlay_protocol: bool | UndefinedType = Undefined, + isis_hello_padding: bool | UndefinedType = Undefined, + isis_metric: int | None | UndefinedType = Undefined, + isis_circuit_type: Literal["level-1", "level-2", "level-1-2"] | None | UndefinedType = Undefined, + isis_authentication_mode: Literal["md5", "text"] | None | UndefinedType = Undefined, + isis_authentication_key: str | None | UndefinedType = Undefined, + isis_network_type: Literal["point-to-point", "broadcast"] | UndefinedType = Undefined, + mpls_ip: bool | None | UndefinedType = Undefined, + mpls_ldp: bool | None | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + bfd: bool | None | UndefinedType = Undefined, + ptp: Ptp | UndefinedType = Undefined, + sflow: bool | None | UndefinedType = Undefined, + underlay_multicast: bool | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + qos_profile: str | None | UndefinedType = Undefined, + macsec_profile: str | None | UndefinedType = Undefined, + port_channel: PortChannel | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + routing_protocol: Literal["ebgp"] | None | UndefinedType = Undefined, + structured_config: dict | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + P2pLinksProfilesItem. + + + Subclass of AvdModel. + + Args: + name: P2P profile name. Any variable supported under `p2p_links` can be inherited from a profile. + id: + Unique id per subnet_summary. Used to calculate ip addresses. + Required with ip_pool. ID starting + from 1. + speed: + Speed should be set in the format `` or `forced ` or `auto + `. + ip_pool: + P2P pool name. IP Pool defined under p2p_links_ip_pools. A /31 will be taken from the pool per P2P + link. + subnet: IPv4 address/Mask. Subnet used on this P2P link. + ip: + Specific IP addresses used on this P2P link. + + Subclass of AvdList with `str` items. + ipv6_enable: + Allows turning on ipv6 for the link or profile (also autodetected based on underlay_rfc5549 and + include_in_underlay_protocol). + nodes: + Nodes where this link should be configured. + + Subclass of AvdList with `str` items. + interfaces: + Interfaces where this link should be configured and Required unless using port-channels. + + Subclass + of AvdList with `str` items. + field_as: + AS numbers for BGP. + Required with bgp peering. + + + Subclass of AvdList with `str` items. + descriptions: + Interface descriptions. + + Subclass of AvdList with `str` items. + include_in_underlay_protocol: Add this interface to underlay routing protocol. + isis_hello_padding: isis_hello_padding + isis_metric: isis_metric + isis_circuit_type: isis_circuit_type + isis_authentication_mode: isis_authentication_mode + isis_authentication_key: Type-7 encrypted password. + isis_network_type: isis_network_type + mpls_ip: MPLS parameters. Default value is true if switch.mpls_lsr is true. + mpls_ldp: MPLS parameters. Default value is true for ldp underlay variants, otherwise false. + mtu: MTU for this P2P link. Default value same as p2p_uplinks_mtu. + bfd: Enable BFD (only considered for BGP). + ptp: + PTP parameters. + + Subclass of AvdModel. + sflow: Enable sFlow. Overrides `fabric_sflow` setting. + underlay_multicast: + Enable PIM sparse mode. Requires `include_in_underlay_protocol` and the global `underlay_multicast` + to be `true`. + flow_tracking: + Enable flow-tracking. Overrides `fabric_flow_tracking` setting. + + Subclass of AvdModel. + qos_profile: QOS service profile. + macsec_profile: MAC security profile. + port_channel: + Port-channel parameters. + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the point-to-point interface in the final EOS configuration. + routing_protocol: + Enables deviation of the routing protocol used on this link from the fabric underlay default. + - + ebgp: Enforce plain IPv4 BGP peering + structured_config: + Custom structured config for interfaces. + Note! The content of this dictionary is _not_ validated by + the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + _custom_data: _custom_data + + """ + + class P2pLinksProfiles(AvdIndexedList[str, P2pLinksProfilesItem]): + """Subclass of AvdIndexedList with `P2pLinksProfilesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + P2pLinksProfiles._item_type = P2pLinksProfilesItem + + class P2pLinksItem(AvdModel): + """Subclass of AvdModel.""" + + class Nodes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Nodes._item_type = str + + class Ip(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Ip._item_type = str + + class Interfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Interfaces._item_type = str + + class As(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + As._item_type = str + + class Descriptions(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Descriptions._item_type = str + + class Ptp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enabled: bool + """ + Enable PTP. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, enabled: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Ptp. + + + Subclass of AvdModel. + + Args: + enabled: Enable PTP. + _custom_data: _custom_data + + """ + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class PortChannel(AvdModel): + """Subclass of AvdModel.""" + + class NodesChildInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Interfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Interfaces._item_type = str + + _fields: ClassVar[dict] = { + "node": {"type": str}, + "interfaces": {"type": Interfaces}, + "channel_id": {"type": int}, + "_custom_data": {"type": dict}, + } + node: str + interfaces: Interfaces + """ + List of node interfaces. Ex.- [ 'node1 interface1', 'node1 interface2' ]. + + Subclass of AvdList with + `str` items. + """ + channel_id: int | None + """ + Port-Channel ID. If no channel_id is specified, an id is generated from the first switch port in the + port channel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + node: str | UndefinedType = Undefined, + interfaces: Interfaces | UndefinedType = Undefined, + channel_id: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NodesChildInterfacesItem. + + + Subclass of AvdModel. + + Args: + node: node + interfaces: + List of node interfaces. Ex.- [ 'node1 interface1', 'node1 interface2' ]. + + Subclass of AvdList with + `str` items. + channel_id: + Port-Channel ID. If no channel_id is specified, an id is generated from the first switch port in the + port channel. + _custom_data: _custom_data + + """ + + class NodesChildInterfaces(AvdIndexedList[str, NodesChildInterfacesItem]): + """Subclass of AvdIndexedList with `NodesChildInterfacesItem` items. Primary key is `node` (`str`).""" + + _primary_key: ClassVar[str] = "node" + + NodesChildInterfaces._item_type = NodesChildInterfacesItem + + _fields: ClassVar[dict] = { + "description": {"type": str}, + "mode": {"type": str, "default": "active"}, + "nodes_child_interfaces": {"type": NodesChildInterfaces}, + "_custom_data": {"type": dict}, + } + description: str | None + """ + Description or description template to be used on the port-channel interface. + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `peer`: The name of the peer. + - `interface`: The local port-channel interface name. + - + `peer_interface`: The port-channel interface on the peer. + - `port_channel_id`: The local port- + channel ID. + - `peer_port_channel_id`: The ID of the port-channel on the peer. + + Falls back to the + description on the `p2p_link` if set. Otherwise default description is set by + `default_underlay_p2p_port_channel_description`. + By default the description is templated from the + name and port_channel interface of the peer. + """ + mode: str + """Default value: `"active"`""" + nodes_child_interfaces: NodesChildInterfaces + """Subclass of AvdIndexedList with `NodesChildInterfacesItem` items. Primary key is `node` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + description: str | None | UndefinedType = Undefined, + mode: str | UndefinedType = Undefined, + nodes_child_interfaces: NodesChildInterfaces | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PortChannel. + + + Subclass of AvdModel. + + Args: + description: + Description or description template to be used on the port-channel interface. + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `peer`: The name of the peer. + - `interface`: The local port-channel interface name. + - + `peer_interface`: The port-channel interface on the peer. + - `port_channel_id`: The local port- + channel ID. + - `peer_port_channel_id`: The ID of the port-channel on the peer. + + Falls back to the + description on the `p2p_link` if set. Otherwise default description is set by + `default_underlay_p2p_port_channel_description`. + By default the description is templated from the + name and port_channel interface of the peer. + mode: mode + nodes_child_interfaces: Subclass of AvdIndexedList with `NodesChildInterfacesItem` items. Primary key is `node` (`str`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "nodes": {"type": Nodes}, + "profile": {"type": str}, + "id": {"type": int}, + "speed": {"type": str}, + "ip_pool": {"type": str}, + "subnet": {"type": str}, + "ip": {"type": Ip}, + "ipv6_enable": {"type": bool, "default": False}, + "interfaces": {"type": Interfaces}, + "field_as": {"type": As}, + "descriptions": {"type": Descriptions}, + "include_in_underlay_protocol": {"type": bool, "default": True}, + "isis_hello_padding": {"type": bool, "default": True}, + "isis_metric": {"type": int}, + "isis_circuit_type": {"type": str}, + "isis_authentication_mode": {"type": str}, + "isis_authentication_key": {"type": str}, + "isis_network_type": {"type": str, "default": "point-to-point"}, + "mpls_ip": {"type": bool}, + "mpls_ldp": {"type": bool}, + "mtu": {"type": int}, + "bfd": {"type": bool}, + "ptp": {"type": Ptp}, + "sflow": {"type": bool}, + "underlay_multicast": {"type": bool, "default": False}, + "flow_tracking": {"type": FlowTracking}, + "qos_profile": {"type": str}, + "macsec_profile": {"type": str}, + "port_channel": {"type": PortChannel}, + "raw_eos_cli": {"type": str}, + "routing_protocol": {"type": str}, + "structured_config": {"type": dict}, + "_custom_data": {"type": dict}, + } + _field_to_key_map: ClassVar[dict] = {"field_as": "as"} + _key_to_field_map: ClassVar[dict] = {"as": "field_as"} + nodes: Nodes + """ + Nodes where this link should be configured. + + Subclass of AvdList with `str` items. + """ + profile: str | None + """P2P profile name. Profile defined under p2p_profiles.""" + id: int | None + """ + Unique id per subnet_summary. Used to calculate ip addresses. + Required with ip_pool. ID starting + from 1. + """ + speed: str | None + """ + Speed should be set in the format `` or `forced ` or `auto + `. + """ + ip_pool: str | None + """ + P2P pool name. IP Pool defined under p2p_links_ip_pools. A /31 will be taken from the pool per P2P + link. + """ + subnet: str | None + """IPv4 address/Mask. Subnet used on this P2P link.""" + ip: Ip + """ + Specific IP addresses used on this P2P link. + + Subclass of AvdList with `str` items. + """ + ipv6_enable: bool + """ + Allows turning on ipv6 for the link or profile (also autodetected based on underlay_rfc5549 and + include_in_underlay_protocol). + + Default value: `False` + """ + interfaces: Interfaces + """ + Interfaces where this link should be configured and Required unless using port-channels. + + Subclass + of AvdList with `str` items. + """ + field_as: As + """ + AS numbers for BGP. + Required with bgp peering. + + + Subclass of AvdList with `str` items. + """ + descriptions: Descriptions + """ + Interface descriptions. + + Subclass of AvdList with `str` items. + """ + include_in_underlay_protocol: bool + """ + Add this interface to underlay routing protocol. + + Default value: `True` + """ + isis_hello_padding: bool + """Default value: `True`""" + isis_metric: int | None + isis_circuit_type: Literal["level-1", "level-2", "level-1-2"] | None + isis_authentication_mode: Literal["md5", "text"] | None + isis_authentication_key: str | None + """Type-7 encrypted password.""" + isis_network_type: Literal["point-to-point", "broadcast"] + """Default value: `"point-to-point"`""" + mpls_ip: bool | None + """MPLS parameters. Default value is true if switch.mpls_lsr is true.""" + mpls_ldp: bool | None + """MPLS parameters. Default value is true for ldp underlay variants, otherwise false.""" + mtu: int | None + """MTU for this P2P link. Default value same as p2p_uplinks_mtu.""" + bfd: bool | None + """Enable BFD (only considered for BGP).""" + ptp: Ptp + """ + PTP parameters. + + Subclass of AvdModel. + """ + sflow: bool | None + """Enable sFlow. Overrides `fabric_sflow` setting.""" + underlay_multicast: bool + """ + Enable PIM sparse mode. Requires `include_in_underlay_protocol` and the global `underlay_multicast` + to be `true`. + + Default value: `False` + """ + flow_tracking: FlowTracking + """ + Enable flow-tracking. Overrides `fabric_flow_tracking` setting. + + Subclass of AvdModel. + """ + qos_profile: str | None + """QOS service profile.""" + macsec_profile: str | None + """MAC security profile.""" + port_channel: PortChannel + """ + Port-channel parameters. + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the point-to-point interface in the final EOS configuration.""" + routing_protocol: Literal["ebgp"] | None + """ + Enables deviation of the routing protocol used on this link from the fabric underlay default. + - + ebgp: Enforce plain IPv4 BGP peering + """ + structured_config: dict + """ + Custom structured config for interfaces. + Note! The content of this dictionary is _not_ validated by + the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + nodes: Nodes | UndefinedType = Undefined, + profile: str | None | UndefinedType = Undefined, + id: int | None | UndefinedType = Undefined, + speed: str | None | UndefinedType = Undefined, + ip_pool: str | None | UndefinedType = Undefined, + subnet: str | None | UndefinedType = Undefined, + ip: Ip | UndefinedType = Undefined, + ipv6_enable: bool | UndefinedType = Undefined, + interfaces: Interfaces | UndefinedType = Undefined, + field_as: As | UndefinedType = Undefined, + descriptions: Descriptions | UndefinedType = Undefined, + include_in_underlay_protocol: bool | UndefinedType = Undefined, + isis_hello_padding: bool | UndefinedType = Undefined, + isis_metric: int | None | UndefinedType = Undefined, + isis_circuit_type: Literal["level-1", "level-2", "level-1-2"] | None | UndefinedType = Undefined, + isis_authentication_mode: Literal["md5", "text"] | None | UndefinedType = Undefined, + isis_authentication_key: str | None | UndefinedType = Undefined, + isis_network_type: Literal["point-to-point", "broadcast"] | UndefinedType = Undefined, + mpls_ip: bool | None | UndefinedType = Undefined, + mpls_ldp: bool | None | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + bfd: bool | None | UndefinedType = Undefined, + ptp: Ptp | UndefinedType = Undefined, + sflow: bool | None | UndefinedType = Undefined, + underlay_multicast: bool | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + qos_profile: str | None | UndefinedType = Undefined, + macsec_profile: str | None | UndefinedType = Undefined, + port_channel: PortChannel | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + routing_protocol: Literal["ebgp"] | None | UndefinedType = Undefined, + structured_config: dict | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + P2pLinksItem. + + + Subclass of AvdModel. + + Args: + nodes: + Nodes where this link should be configured. + + Subclass of AvdList with `str` items. + profile: P2P profile name. Profile defined under p2p_profiles. + id: + Unique id per subnet_summary. Used to calculate ip addresses. + Required with ip_pool. ID starting + from 1. + speed: + Speed should be set in the format `` or `forced ` or `auto + `. + ip_pool: + P2P pool name. IP Pool defined under p2p_links_ip_pools. A /31 will be taken from the pool per P2P + link. + subnet: IPv4 address/Mask. Subnet used on this P2P link. + ip: + Specific IP addresses used on this P2P link. + + Subclass of AvdList with `str` items. + ipv6_enable: + Allows turning on ipv6 for the link or profile (also autodetected based on underlay_rfc5549 and + include_in_underlay_protocol). + interfaces: + Interfaces where this link should be configured and Required unless using port-channels. + + Subclass + of AvdList with `str` items. + field_as: + AS numbers for BGP. + Required with bgp peering. + + + Subclass of AvdList with `str` items. + descriptions: + Interface descriptions. + + Subclass of AvdList with `str` items. + include_in_underlay_protocol: Add this interface to underlay routing protocol. + isis_hello_padding: isis_hello_padding + isis_metric: isis_metric + isis_circuit_type: isis_circuit_type + isis_authentication_mode: isis_authentication_mode + isis_authentication_key: Type-7 encrypted password. + isis_network_type: isis_network_type + mpls_ip: MPLS parameters. Default value is true if switch.mpls_lsr is true. + mpls_ldp: MPLS parameters. Default value is true for ldp underlay variants, otherwise false. + mtu: MTU for this P2P link. Default value same as p2p_uplinks_mtu. + bfd: Enable BFD (only considered for BGP). + ptp: + PTP parameters. + + Subclass of AvdModel. + sflow: Enable sFlow. Overrides `fabric_sflow` setting. + underlay_multicast: + Enable PIM sparse mode. Requires `include_in_underlay_protocol` and the global `underlay_multicast` + to be `true`. + flow_tracking: + Enable flow-tracking. Overrides `fabric_flow_tracking` setting. + + Subclass of AvdModel. + qos_profile: QOS service profile. + macsec_profile: MAC security profile. + port_channel: + Port-channel parameters. + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the point-to-point interface in the final EOS configuration. + routing_protocol: + Enables deviation of the routing protocol used on this link from the fabric underlay default. + - + ebgp: Enforce plain IPv4 BGP peering + structured_config: + Custom structured config for interfaces. + Note! The content of this dictionary is _not_ validated by + the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + _custom_data: _custom_data + + """ + + class P2pLinks(AvdList[P2pLinksItem]): + """Subclass of AvdList with `P2pLinksItem` items.""" + + P2pLinks._item_type = P2pLinksItem + + _fields: ClassVar[dict] = { + "p2p_links_ip_pools": {"type": P2pLinksIpPools}, + "p2p_links_profiles": {"type": P2pLinksProfiles}, + "p2p_links": {"type": P2pLinks}, + "_custom_data": {"type": dict}, + } + p2p_links_ip_pools: P2pLinksIpPools + """Subclass of AvdIndexedList with `P2pLinksIpPoolsItem` items. Primary key is `name` (`str`).""" + p2p_links_profiles: P2pLinksProfiles + """Subclass of AvdIndexedList with `P2pLinksProfilesItem` items. Primary key is `name` (`str`).""" + p2p_links: P2pLinks + """Subclass of AvdList with `P2pLinksItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + p2p_links_ip_pools: P2pLinksIpPools | UndefinedType = Undefined, + p2p_links_profiles: P2pLinksProfiles | UndefinedType = Undefined, + p2p_links: P2pLinks | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CoreInterfaces. + + + Subclass of AvdModel. + + Args: + p2p_links_ip_pools: Subclass of AvdIndexedList with `P2pLinksIpPoolsItem` items. Primary key is `name` (`str`). + p2p_links_profiles: Subclass of AvdIndexedList with `P2pLinksProfilesItem` items. Primary key is `name` (`str`). + p2p_links: Subclass of AvdList with `P2pLinksItem` items. + _custom_data: _custom_data + + """ + + class CustomStructuredConfigurationPrefix(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + CustomStructuredConfigurationPrefix._item_type = str + + class CvPathfinderGlobalSitesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "description": {"type": str}, "location": {"type": str}, "_custom_data": {"type": dict}} + name: str + """The site name.""" + description: str | None + location: str | None + """Location as a string is resolved on Cloudvision.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + location: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CvPathfinderGlobalSitesItem. + + + Subclass of AvdModel. + + Args: + name: The site name. + description: description + location: Location as a string is resolved on Cloudvision. + _custom_data: _custom_data + + """ + + class CvPathfinderGlobalSites(AvdIndexedList[str, CvPathfinderGlobalSitesItem]): + """Subclass of AvdIndexedList with `CvPathfinderGlobalSitesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + CvPathfinderGlobalSites._item_type = CvPathfinderGlobalSitesItem + + class CvPathfinderInternetExitPoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + class Zscaler(AvdModel): + """Subclass of AvdModel.""" + + class Firewall(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool, "default": False}, "ips": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enabled: bool + """ + Enforce firewall controls. + + Default value: `False` + """ + ips: bool + """ + Enable IPS Controls for the firewall. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + ips: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Firewall. + + + Subclass of AvdModel. + + Args: + enabled: Enforce firewall controls. + ips: Enable IPS Controls for the firewall. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "ipsec_key_salt": {"type": str}, + "domain_name": {"type": str}, + "encrypt_traffic": {"type": bool, "default": True}, + "download_bandwidth": {"type": int}, + "upload_bandwidth": {"type": int}, + "firewall": {"type": Firewall}, + "acceptable_use_policy": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + ipsec_key_salt: str + """ + "Salt" used for auto generation of encryption keys for IPsec tunnels to Zscaler. + The keys will be + generated as a hash of `salt__`. + Since this salt can be used to deduct the + encryption key, it is recommended to use vault. + """ + domain_name: str + """Domain name as configured in Zscaler for the tenant. Used as UFQDN suffix for authentication.""" + encrypt_traffic: bool + """ + When `true` the traffic going over the tunnels will be encrypted with AES-256-GCM. Otherwise the + traffic will be using NULL encryption. + Note that encryption requires a subscription on the Zscaler + account. + + Default value: `True` + """ + download_bandwidth: int | None + """Maximum allowed download bandwidth in Mbps for each device using this policy.""" + upload_bandwidth: int | None + """Maximum allowed upload bandwidth in Mbps for each device using this policy.""" + firewall: Firewall + """Subclass of AvdModel.""" + acceptable_use_policy: bool + """ + Display an Acceptable Use Policy (AUP) and require users to accept it. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipsec_key_salt: str | UndefinedType = Undefined, + domain_name: str | UndefinedType = Undefined, + encrypt_traffic: bool | UndefinedType = Undefined, + download_bandwidth: int | None | UndefinedType = Undefined, + upload_bandwidth: int | None | UndefinedType = Undefined, + firewall: Firewall | UndefinedType = Undefined, + acceptable_use_policy: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Zscaler. + + + Subclass of AvdModel. + + Args: + ipsec_key_salt: + "Salt" used for auto generation of encryption keys for IPsec tunnels to Zscaler. + The keys will be + generated as a hash of `salt__`. + Since this salt can be used to deduct the + encryption key, it is recommended to use vault. + domain_name: Domain name as configured in Zscaler for the tenant. Used as UFQDN suffix for authentication. + encrypt_traffic: + When `true` the traffic going over the tunnels will be encrypted with AES-256-GCM. Otherwise the + traffic will be using NULL encryption. + Note that encryption requires a subscription on the Zscaler + account. + download_bandwidth: Maximum allowed download bandwidth in Mbps for each device using this policy. + upload_bandwidth: Maximum allowed upload bandwidth in Mbps for each device using this policy. + firewall: Subclass of AvdModel. + acceptable_use_policy: Display an Acceptable Use Policy (AUP) and require users to accept it. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "type": {"type": str}, + "fallback_to_system_default": {"type": bool, "default": True}, + "zscaler": {"type": Zscaler}, + "_custom_data": {"type": dict}, + } + name: str + """Internet-exit policy name.""" + type: Literal["direct", "zscaler"] + """ + Internet-exit policy type. + direct: Exit directly over wan interfaces + zscaler: Exit using Zscaler + secure web gateway service + """ + fallback_to_system_default: bool + """ + Add system default exit-group at the end of the policy. + + Default value: `True` + """ + zscaler: Zscaler + """ + Zscaler information. Only used if `type` is 'zscaler'. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + type: Literal["direct", "zscaler"] | UndefinedType = Undefined, + fallback_to_system_default: bool | UndefinedType = Undefined, + zscaler: Zscaler | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CvPathfinderInternetExitPoliciesItem. + + + Subclass of AvdModel. + + Args: + name: Internet-exit policy name. + type: + Internet-exit policy type. + direct: Exit directly over wan interfaces + zscaler: Exit using Zscaler + secure web gateway service + fallback_to_system_default: Add system default exit-group at the end of the policy. + zscaler: + Zscaler information. Only used if `type` is 'zscaler'. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class CvPathfinderInternetExitPolicies(AvdIndexedList[str, CvPathfinderInternetExitPoliciesItem]): + """ + Subclass of AvdIndexedList with `CvPathfinderInternetExitPoliciesItem` items. Primary key is `name` + (`str`). + """ + + _primary_key: ClassVar[str] = "name" + + CvPathfinderInternetExitPolicies._item_type = CvPathfinderInternetExitPoliciesItem + + class CvPathfinderRegionsItem(AvdModel): + """Subclass of AvdModel.""" + + class SitesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "description": {"type": str}, + "id": {"type": int}, + "location": {"type": str}, + "site_contact": {"type": str}, + "site_after_hours_contact": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """The site name.""" + description: str | None + id: int + """ + The site ID must be unique within a zone. + Given that all the sites are placed in a zone named after + the region, the site ID must be unique within a region. + """ + location: str | None + """Location as a string is resolved on Cloudvision.""" + site_contact: str | None + site_after_hours_contact: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + id: int | UndefinedType = Undefined, + location: str | None | UndefinedType = Undefined, + site_contact: str | None | UndefinedType = Undefined, + site_after_hours_contact: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SitesItem. + + + Subclass of AvdModel. + + Args: + name: The site name. + description: description + id: + The site ID must be unique within a zone. + Given that all the sites are placed in a zone named after + the region, the site ID must be unique within a region. + location: Location as a string is resolved on Cloudvision. + site_contact: site_contact + site_after_hours_contact: site_after_hours_contact + _custom_data: _custom_data + + """ + + class Sites(AvdIndexedList[str, SitesItem]): + """Subclass of AvdIndexedList with `SitesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Sites._item_type = SitesItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "description": {"type": str}, + "id": {"type": int}, + "sites": {"type": Sites}, + "_custom_data": {"type": dict}, + } + name: str + description: str | None + id: int + """The region ID must be unique for the whole WAN deployment.""" + sites: Sites + """ + All sites are placed in a default zone "-ZONE" with ID 1. + + Subclass of AvdIndexedList + with `SitesItem` items. Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + id: int | UndefinedType = Undefined, + sites: Sites | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CvPathfinderRegionsItem. + + + Subclass of AvdModel. + + Args: + name: name + description: description + id: The region ID must be unique for the whole WAN deployment. + sites: + All sites are placed in a default zone "-ZONE" with ID 1. + + Subclass of AvdIndexedList + with `SitesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class CvPathfinderRegions(AvdIndexedList[str, CvPathfinderRegionsItem]): + """Subclass of AvdIndexedList with `CvPathfinderRegionsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + CvPathfinderRegions._item_type = CvPathfinderRegionsItem + + class CvTopologyItem(AvdModel): + """Subclass of AvdModel.""" + + class InterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "neighbor": {"type": str}, "neighbor_interface": {"type": str}, "_custom_data": {"type": dict}} + name: str + neighbor: str | None + neighbor_interface: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + neighbor: str | None | UndefinedType = Undefined, + neighbor_interface: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + InterfacesItem. + + + Subclass of AvdModel. + + Args: + name: name + neighbor: neighbor + neighbor_interface: neighbor_interface + _custom_data: _custom_data + + """ + + class Interfaces(AvdIndexedList[str, InterfacesItem]): + """Subclass of AvdIndexedList with `InterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Interfaces._item_type = InterfacesItem + + _fields: ClassVar[dict] = {"hostname": {"type": str}, "platform": {"type": str}, "interfaces": {"type": Interfaces}, "_custom_data": {"type": dict}} + hostname: str + platform: str + interfaces: Interfaces + """Subclass of AvdIndexedList with `InterfacesItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: str | UndefinedType = Undefined, + platform: str | UndefinedType = Undefined, + interfaces: Interfaces | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CvTopologyItem. + + + Subclass of AvdModel. + + Args: + hostname: hostname + platform: platform + interfaces: Subclass of AvdIndexedList with `InterfacesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class CvTopology(AvdIndexedList[str, CvTopologyItem]): + """Subclass of AvdIndexedList with `CvTopologyItem` items. Primary key is `hostname` (`str`).""" + + _primary_key: ClassVar[str] = "hostname" + + CvTopology._item_type = CvTopologyItem + + class CvpInstanceIps(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + CvpInstanceIps._item_type = str + + class DefaultInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Types(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Types._item_type = str + + class Platforms(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Platforms._item_type = str + + class UplinkInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkInterfaces._item_type = str + + class MlagInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MlagInterfaces._item_type = str + + class DownlinkInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DownlinkInterfaces._item_type = str + + _fields: ClassVar[dict] = { + "types": {"type": Types}, + "platforms": {"type": Platforms}, + "uplink_interfaces": {"type": UplinkInterfaces}, + "mlag_interfaces": {"type": MlagInterfaces}, + "downlink_interfaces": {"type": DownlinkInterfaces}, + "_custom_data": {"type": dict}, + } + types: Types + """ + List of node type keys. + + Subclass of AvdList with `str` items. + """ + platforms: Platforms + """ + List of platform families. + This is defined as a Python regular expression that matches the full + platform type. + + + Subclass of AvdList with `str` items. + """ + uplink_interfaces: UplinkInterfaces + """ + List of uplink interfaces or uplink interface ranges. + + Subclass of AvdList with `str` items. + """ + mlag_interfaces: MlagInterfaces + """ + List of MLAG interfaces or MLAG interface ranges. + + Subclass of AvdList with `str` items. + """ + downlink_interfaces: DownlinkInterfaces + """ + List of downlink interfaces or downlink interface ranges. + + Subclass of AvdList with `str` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + types: Types | UndefinedType = Undefined, + platforms: Platforms | UndefinedType = Undefined, + uplink_interfaces: UplinkInterfaces | UndefinedType = Undefined, + mlag_interfaces: MlagInterfaces | UndefinedType = Undefined, + downlink_interfaces: DownlinkInterfaces | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultInterfacesItem. + + + Subclass of AvdModel. + + Args: + types: + List of node type keys. + + Subclass of AvdList with `str` items. + platforms: + List of platform families. + This is defined as a Python regular expression that matches the full + platform type. + + + Subclass of AvdList with `str` items. + uplink_interfaces: + List of uplink interfaces or uplink interface ranges. + + Subclass of AvdList with `str` items. + mlag_interfaces: + List of MLAG interfaces or MLAG interface ranges. + + Subclass of AvdList with `str` items. + downlink_interfaces: + List of downlink interfaces or downlink interface ranges. + + Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class DefaultInterfaces(AvdList[DefaultInterfacesItem]): + """Subclass of AvdList with `DefaultInterfacesItem` items.""" + + DefaultInterfaces._item_type = DefaultInterfacesItem + + class DefaultNodeTypesItem(AvdModel): + """Subclass of AvdModel.""" + + class MatchHostnames(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MatchHostnames._item_type = str + + _fields: ClassVar[dict] = {"node_type": {"type": str}, "match_hostnames": {"type": MatchHostnames}, "_custom_data": {"type": dict}} + node_type: str + """Resulting node type when regex matches.""" + match_hostnames: MatchHostnames + """ + Regular expressions to match against hostnames. + + Subclass of AvdList with `str` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + node_type: str | UndefinedType = Undefined, + match_hostnames: MatchHostnames | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultNodeTypesItem. + + + Subclass of AvdModel. + + Args: + node_type: Resulting node type when regex matches. + match_hostnames: + Regular expressions to match against hostnames. + + Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class DefaultNodeTypes(AvdIndexedList[str, DefaultNodeTypesItem]): + """Subclass of AvdIndexedList with `DefaultNodeTypesItem` items. Primary key is `node_type` (`str`).""" + + _primary_key: ClassVar[str] = "node_type" + + DefaultNodeTypes._item_type = DefaultNodeTypesItem + + class Design(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"type": {"type": str, "default": "l3ls-evpn"}, "_custom_data": {"type": dict}} + type: Literal["l3ls-evpn", "mpls", "l2ls"] + """ + By setting the design.type variable, the default node-types and templates described in these + documents will be used. + + Default value: `"l3ls-evpn"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, type: Literal["l3ls-evpn", "mpls", "l2ls"] | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Design. + + + Subclass of AvdModel. + + Args: + type: + By setting the design.type variable, the default node-types and templates described in these + documents will be used. + _custom_data: _custom_data + + """ + + class EosDesignsCustomTemplatesItem(AvdModel): + """Subclass of AvdModel.""" + + class Options(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "list_merge": {"type": str, "default": "append_rp"}, + "strip_empty_keys": {"type": bool, "default": True}, + "_custom_data": {"type": dict}, + } + list_merge: str + """ + Merge strategy for lists. + + Default value: `"append_rp"` + """ + strip_empty_keys: bool + """ + Filter out keys from the generated output if value is null/none/undefined. + + Default value: `True` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + list_merge: str | UndefinedType = Undefined, + strip_empty_keys: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Options. + + + Subclass of AvdModel. + + Args: + list_merge: Merge strategy for lists. + strip_empty_keys: Filter out keys from the generated output if value is null/none/undefined. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"template": {"type": str}, "options": {"type": Options}, "_custom_data": {"type": dict}} + template: str + """Template file.""" + options: Options + """ + Template options. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + template: str | UndefinedType = Undefined, + options: Options | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EosDesignsCustomTemplatesItem. + + + Subclass of AvdModel. + + Args: + template: Template file. + options: + Template options. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class EosDesignsCustomTemplates(AvdList[EosDesignsCustomTemplatesItem]): + """Subclass of AvdList with `EosDesignsCustomTemplatesItem` items.""" + + EosDesignsCustomTemplates._item_type = EosDesignsCustomTemplatesItem + + class EosDesignsDocumentation(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enable": {"type": bool, "default": True}, + "connected_endpoints": {"type": bool, "default": False}, + "topology_csv": {"type": bool, "default": False}, + "p2p_links_csv": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + enable: bool + """ + Generate fabric-wide documentation. + + Default value: `True` + """ + connected_endpoints: bool + """ + Include connected endpoints in the fabric-wide documentation. + This is `false` by default to avoid + cluttering documentation for projects with thousands of endpoints. + + Default value: `False` + """ + topology_csv: bool + """ + Generate Topology CSV with all interfaces towards other devices. + + Default value: `False` + """ + p2p_links_csv: bool + """ + Generate P2P links CSV with all routed point-to-point links between devices. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enable: bool | UndefinedType = Undefined, + connected_endpoints: bool | UndefinedType = Undefined, + topology_csv: bool | UndefinedType = Undefined, + p2p_links_csv: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EosDesignsDocumentation. + + + Subclass of AvdModel. + + Args: + enable: Generate fabric-wide documentation. + connected_endpoints: + Include connected endpoints in the fabric-wide documentation. + This is `false` by default to avoid + cluttering documentation for projects with thousands of endpoints. + topology_csv: Generate Topology CSV with all interfaces towards other devices. + p2p_links_csv: Generate P2P links CSV with all routed point-to-point links between devices. + _custom_data: _custom_data + + """ + + class EventHandlers(EosCliConfigGen.EventHandlers): + pass + + class EvpnHostflapDetection(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "threshold": {"type": int, "default": 5}, + "window": {"type": int, "default": 180}, + "expiry_timeout": {"type": int}, + "_custom_data": {"type": dict}, + } + enabled: bool + """ + If set to false it will disable EVPN host-flap detection. + + Default value: `True` + """ + threshold: int + """ + Minimum number of MAC moves that indicate a MAC duplication issue. + + Default value: `5` + """ + window: int + """ + Time (in seconds) to detect a MAC duplication issue. + + Default value: `180` + """ + expiry_timeout: int | None + """Time (in seconds) to purge a MAC duplication issue.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + threshold: int | UndefinedType = Undefined, + window: int | UndefinedType = Undefined, + expiry_timeout: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnHostflapDetection. + + + Subclass of AvdModel. + + Args: + enabled: If set to false it will disable EVPN host-flap detection. + threshold: Minimum number of MAC moves that indicate a MAC duplication issue. + window: Time (in seconds) to detect a MAC duplication issue. + expiry_timeout: Time (in seconds) to purge a MAC duplication issue. + _custom_data: _custom_data + + """ + + class EvpnVlanBundlesItem(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"raw_eos_cli": {"type": str}, "_custom_data": {"type": dict}} + raw_eos_cli: str | None + """EOS cli commands rendered on router_bgp.vlans-aware-bundle.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, raw_eos_cli: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + raw_eos_cli: EOS cli commands rendered on router_bgp.vlans-aware-bundle. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "id": {"type": int}, + "rt_override": {"type": str}, + "rd_override": {"type": str}, + "evpn_l2_multi_domain": {"type": bool}, + "bgp": {"type": Bgp}, + "_custom_data": {"type": dict}, + } + name: str + """ + Specify an EVPN vlan-aware-bundle name. + EVPN vlan-aware-bundles group VLANs and define common + settings. + """ + id: int + """ + "id" may be used for vlan-aware-bundle RD/RT ID so it should not overlap with l2vlan IDs which are + not part of this bundle. + See "overlay_rd_type" and "overlay_rt_type" for details. + """ + rt_override: str | None + """ + By default the MAC VRF bundle RT will be derived from mac_vrf_id_base + bundle_id. + The rt_override + allows us to override this value and statically define it. + rt_override will default to vni_override + if set. + + rt_override supports two formats: + - A single number which will be used in the RT fields + instead of mac_vrf_id/mac_vrf_vni (see 'overlay_rt_type' for details). + - A full RT string with + colon separator which will override the full RT. + """ + rd_override: str | None + """ + By default the MAC VRF bundle RD will be derived from mac_vrf_id_base + bundle_id. + The rt_override + allows us to override this value and statically define it. + rd_override will default to rt_override + or vni_override if set. + + rd_override supports two formats: + - A single number which will be used in + the RD assigned number field instead of mac_vrf_id/mac_vrf_vni (see 'overlay_rd_type' for details). + - A full RD string with colon separator which will override the full RD. + """ + evpn_l2_multi_domain: bool | None + """ + Explicitly extend VLAN-Aware Bundle to remote EVPN domains. + Overrides + `.[].evpn_l2_multi_domain`. + """ + bgp: Bgp + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + id: int | UndefinedType = Undefined, + rt_override: str | None | UndefinedType = Undefined, + rd_override: str | None | UndefinedType = Undefined, + evpn_l2_multi_domain: bool | None | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnVlanBundlesItem. + + + Subclass of AvdModel. + + Args: + name: + Specify an EVPN vlan-aware-bundle name. + EVPN vlan-aware-bundles group VLANs and define common + settings. + id: + "id" may be used for vlan-aware-bundle RD/RT ID so it should not overlap with l2vlan IDs which are + not part of this bundle. + See "overlay_rd_type" and "overlay_rt_type" for details. + rt_override: + By default the MAC VRF bundle RT will be derived from mac_vrf_id_base + bundle_id. + The rt_override + allows us to override this value and statically define it. + rt_override will default to vni_override + if set. + + rt_override supports two formats: + - A single number which will be used in the RT fields + instead of mac_vrf_id/mac_vrf_vni (see 'overlay_rt_type' for details). + - A full RT string with + colon separator which will override the full RT. + rd_override: + By default the MAC VRF bundle RD will be derived from mac_vrf_id_base + bundle_id. + The rt_override + allows us to override this value and statically define it. + rd_override will default to rt_override + or vni_override if set. + + rd_override supports two formats: + - A single number which will be used in + the RD assigned number field instead of mac_vrf_id/mac_vrf_vni (see 'overlay_rd_type' for details). + - A full RD string with colon separator which will override the full RD. + evpn_l2_multi_domain: + Explicitly extend VLAN-Aware Bundle to remote EVPN domains. + Overrides + `.[].evpn_l2_multi_domain`. + bgp: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class EvpnVlanBundles(AvdIndexedList[str, EvpnVlanBundlesItem]): + """Subclass of AvdIndexedList with `EvpnVlanBundlesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + EvpnVlanBundles._item_type = EvpnVlanBundlesItem + + class FabricFlowTracking(AvdModel): + """Subclass of AvdModel.""" + + class Uplinks(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "name": {"type": str, "default": "FLOW-TRACKER"}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + name: str + """ + Flow tracker name as defined in flow_tracking_settings. + + Default value: `"FLOW-TRACKER"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Uplinks. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class Downlinks(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "name": {"type": str, "default": "FLOW-TRACKER"}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + name: str + """ + Flow tracker name as defined in flow_tracking_settings. + + Default value: `"FLOW-TRACKER"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Downlinks. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class Endpoints(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "name": {"type": str, "default": "FLOW-TRACKER"}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + name: str + """ + Flow tracker name as defined in flow_tracking_settings. + + Default value: `"FLOW-TRACKER"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Endpoints. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class L3Edge(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "name": {"type": str, "default": "FLOW-TRACKER"}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + name: str + """ + Flow tracker name as defined in flow_tracking_settings. + + Default value: `"FLOW-TRACKER"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L3Edge. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class CoreInterfaces(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "name": {"type": str, "default": "FLOW-TRACKER"}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + name: str + """ + Flow tracker name as defined in flow_tracking_settings. + + Default value: `"FLOW-TRACKER"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CoreInterfaces. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class MlagInterfaces(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "name": {"type": str, "default": "FLOW-TRACKER"}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + name: str + """ + Flow tracker name as defined in flow_tracking_settings. + + Default value: `"FLOW-TRACKER"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MlagInterfaces. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class L3Interfaces(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "name": {"type": str, "default": "FLOW-TRACKER"}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + name: str + """ + Flow tracker name as defined in flow_tracking_settings. + + Default value: `"FLOW-TRACKER"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L3Interfaces. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class DpsInterfaces(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "name": {"type": str, "default": "FLOW-TRACKER"}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + name: str + """ + Flow tracker name as defined in flow_tracking_settings. + + Default value: `"FLOW-TRACKER"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DpsInterfaces. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class DirectWanHaLinks(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "name": {"type": str, "default": "FLOW-TRACKER"}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + name: str + """ + Flow tracker name as defined in flow_tracking_settings. + + Default value: `"FLOW-TRACKER"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectWanHaLinks. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "uplinks": {"type": Uplinks}, + "downlinks": {"type": Downlinks}, + "endpoints": {"type": Endpoints}, + "l3_edge": {"type": L3Edge}, + "core_interfaces": {"type": CoreInterfaces}, + "mlag_interfaces": {"type": MlagInterfaces}, + "l3_interfaces": {"type": L3Interfaces}, + "dps_interfaces": {"type": DpsInterfaces}, + "direct_wan_ha_links": {"type": DirectWanHaLinks}, + "_custom_data": {"type": dict}, + } + uplinks: Uplinks + """ + Enable flow-tracking on all fabric uplinks. + + Subclass of AvdModel. + """ + downlinks: Downlinks + """ + Enable flow-tracking on all fabric downlinks. + + Subclass of AvdModel. + """ + endpoints: Endpoints + """ + Enable flow-tracking on all endpoints ports. + + Subclass of AvdModel. + """ + l3_edge: L3Edge + """ + Enable flow-tracking on all p2p_links defined under l3_edge. + + Subclass of AvdModel. + """ + core_interfaces: CoreInterfaces + """ + Enable flow-tracking on all p2p_links defined under core_interfaces. + + Subclass of AvdModel. + """ + mlag_interfaces: MlagInterfaces + """ + Enable flow-tracking on all MLAG peer interfaces. + + Subclass of AvdModel. + """ + l3_interfaces: L3Interfaces + """ + Enable flow-tracking on all node.l3_interfaces and network-services tenants.vrfs.l3_interfaces. + Subclass of AvdModel. + """ + dps_interfaces: DpsInterfaces + """ + Enable flow-tracking on all dps_interfaces. + + Subclass of AvdModel. + """ + direct_wan_ha_links: DirectWanHaLinks + """ + Enable flow-tracking on all direct WAN HA links. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + uplinks: Uplinks | UndefinedType = Undefined, + downlinks: Downlinks | UndefinedType = Undefined, + endpoints: Endpoints | UndefinedType = Undefined, + l3_edge: L3Edge | UndefinedType = Undefined, + core_interfaces: CoreInterfaces | UndefinedType = Undefined, + mlag_interfaces: MlagInterfaces | UndefinedType = Undefined, + l3_interfaces: L3Interfaces | UndefinedType = Undefined, + dps_interfaces: DpsInterfaces | UndefinedType = Undefined, + direct_wan_ha_links: DirectWanHaLinks | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FabricFlowTracking. + + + Subclass of AvdModel. + + Args: + uplinks: + Enable flow-tracking on all fabric uplinks. + + Subclass of AvdModel. + downlinks: + Enable flow-tracking on all fabric downlinks. + + Subclass of AvdModel. + endpoints: + Enable flow-tracking on all endpoints ports. + + Subclass of AvdModel. + l3_edge: + Enable flow-tracking on all p2p_links defined under l3_edge. + + Subclass of AvdModel. + core_interfaces: + Enable flow-tracking on all p2p_links defined under core_interfaces. + + Subclass of AvdModel. + mlag_interfaces: + Enable flow-tracking on all MLAG peer interfaces. + + Subclass of AvdModel. + l3_interfaces: + Enable flow-tracking on all node.l3_interfaces and network-services tenants.vrfs.l3_interfaces. + Subclass of AvdModel. + dps_interfaces: + Enable flow-tracking on all dps_interfaces. + + Subclass of AvdModel. + direct_wan_ha_links: + Enable flow-tracking on all direct WAN HA links. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class FabricIpAddressing(AvdModel): + """Subclass of AvdModel.""" + + class Mlag(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "algorithm": {"type": str, "default": "first_id"}, + "ipv4_prefix_length": {"type": int, "default": 31}, + "ipv6_prefix_length": {"type": int, "default": 64}, + "_custom_data": {"type": dict}, + } + algorithm: Literal["first_id", "odd_id", "same_subnet"] + """ + This variable defines the Multi-chassis Link Aggregation (MLAG) algorithm used. + Each MLAG link will + have a /31¹ subnet with each subnet allocated from the relevant MLAG pool via a calculated offset. + The offset is calculated using one of the following algorithms: + - first_id: `(mlag_primary_id - 1) + * 2` where `mlag_primary_id` is the ID of the first node defined under the node_group. + This + allocation method will skip every other /31¹ subnet making it less space efficient than `odd_id`. + - odd_id: `(odd_id - 1) / 2`. Requires the node_group to have a node with an odd ID and a node with + an even ID. + - same_subnet: the offset will always be zero. + This allocation method will cause + every MLAG link to be addressed with the same /31¹ subnet. + ¹ The prefix length is configurable with + a default of /31. + + Default value: `"first_id"` + """ + ipv4_prefix_length: int + """ + IPv4 prefix length used for MLAG peer-vlan and L3 point-to-point SVIs over the MLAG peer-link. + + Default value: `31` + """ + ipv6_prefix_length: int + """ + IPv6 prefix length used for MLAG peer-vlan and L3 point-to-point SVIs over the MLAG peer-link. + + Default value: `64` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + algorithm: Literal["first_id", "odd_id", "same_subnet"] | UndefinedType = Undefined, + ipv4_prefix_length: int | UndefinedType = Undefined, + ipv6_prefix_length: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Mlag. + + + Subclass of AvdModel. + + Args: + algorithm: + This variable defines the Multi-chassis Link Aggregation (MLAG) algorithm used. + Each MLAG link will + have a /31¹ subnet with each subnet allocated from the relevant MLAG pool via a calculated offset. + The offset is calculated using one of the following algorithms: + - first_id: `(mlag_primary_id - 1) + * 2` where `mlag_primary_id` is the ID of the first node defined under the node_group. + This + allocation method will skip every other /31¹ subnet making it less space efficient than `odd_id`. + - odd_id: `(odd_id - 1) / 2`. Requires the node_group to have a node with an odd ID and a node with + an even ID. + - same_subnet: the offset will always be zero. + This allocation method will cause + every MLAG link to be addressed with the same /31¹ subnet. + ¹ The prefix length is configurable with + a default of /31. + ipv4_prefix_length: IPv4 prefix length used for MLAG peer-vlan and L3 point-to-point SVIs over the MLAG peer-link. + ipv6_prefix_length: IPv6 prefix length used for MLAG peer-vlan and L3 point-to-point SVIs over the MLAG peer-link. + _custom_data: _custom_data + + """ + + class P2pUplinks(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4_prefix_length": {"type": int, "default": 31}, "_custom_data": {"type": dict}} + ipv4_prefix_length: int + """ + IPv4 prefix length used for L3 point-to-point uplinks. + + Default value: `31` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, ipv4_prefix_length: int | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + P2pUplinks. + + + Subclass of AvdModel. + + Args: + ipv4_prefix_length: IPv4 prefix length used for L3 point-to-point uplinks. + _custom_data: _custom_data + + """ + + class WanHa(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4_prefix_length": {"type": int, "default": 31}, "_custom_data": {"type": dict}} + ipv4_prefix_length: int + """ + IPv4 prefix length used for point-to-point interface for direct WAN HA link. + + Default value: `31` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, ipv4_prefix_length: int | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + WanHa. + + + Subclass of AvdModel. + + Args: + ipv4_prefix_length: IPv4 prefix length used for point-to-point interface for direct WAN HA link. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"mlag": {"type": Mlag}, "p2p_uplinks": {"type": P2pUplinks}, "wan_ha": {"type": WanHa}, "_custom_data": {"type": dict}} + mlag: Mlag + """Subclass of AvdModel.""" + p2p_uplinks: P2pUplinks + """Subclass of AvdModel.""" + wan_ha: WanHa + """ + Allow to manipulate the IP addressing scheme for WAN HA direct subnets. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mlag: Mlag | UndefinedType = Undefined, + p2p_uplinks: P2pUplinks | UndefinedType = Undefined, + wan_ha: WanHa | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FabricIpAddressing. + + + Subclass of AvdModel. + + Args: + mlag: Subclass of AvdModel. + p2p_uplinks: Subclass of AvdModel. + wan_ha: + Allow to manipulate the IP addressing scheme for WAN HA direct subnets. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class FabricSflow(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "uplinks": {"type": bool}, + "downlinks": {"type": bool}, + "endpoints": {"type": bool}, + "l3_edge": {"type": bool}, + "core_interfaces": {"type": bool}, + "mlag_interfaces": {"type": bool}, + "l3_interfaces": {"type": bool}, + "_custom_data": {"type": dict}, + } + uplinks: bool | None + """Enable sFlow on all fabric uplinks.""" + downlinks: bool | None + """Enable sFlow on all fabric downlinks.""" + endpoints: bool | None + """Enable sFlow on all endpoints ports.""" + l3_edge: bool | None + """Enable sFlow on all p2p_links defined under l3_edge.""" + core_interfaces: bool | None + """Enable sFlow on all p2p_links defined under core_interfaces.""" + mlag_interfaces: bool | None + """Enable sFlow on all MLAG peer interfaces.""" + l3_interfaces: bool | None + """Enable sFlow on all l3 interfaces.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + uplinks: bool | None | UndefinedType = Undefined, + downlinks: bool | None | UndefinedType = Undefined, + endpoints: bool | None | UndefinedType = Undefined, + l3_edge: bool | None | UndefinedType = Undefined, + core_interfaces: bool | None | UndefinedType = Undefined, + mlag_interfaces: bool | None | UndefinedType = Undefined, + l3_interfaces: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FabricSflow. + + + Subclass of AvdModel. + + Args: + uplinks: Enable sFlow on all fabric uplinks. + downlinks: Enable sFlow on all fabric downlinks. + endpoints: Enable sFlow on all endpoints ports. + l3_edge: Enable sFlow on all p2p_links defined under l3_edge. + core_interfaces: Enable sFlow on all p2p_links defined under core_interfaces. + mlag_interfaces: Enable sFlow on all MLAG peer interfaces. + l3_interfaces: Enable sFlow on all l3 interfaces. + _custom_data: _custom_data + + """ + + class FlowTrackingSettings(AvdModel): + """Subclass of AvdModel.""" + + class Sampled(AvdModel): + """Subclass of AvdModel.""" + + class Encapsulation(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4_ipv6": {"type": bool}, "mpls": {"type": bool}, "_custom_data": {"type": dict}} + ipv4_ipv6: bool | None + mpls: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4_ipv6: bool | None | UndefinedType = Undefined, + mpls: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Encapsulation. + + + Subclass of AvdModel. + + Args: + ipv4_ipv6: ipv4_ipv6 + mpls: mpls + _custom_data: _custom_data + + """ + + class HardwareOffload(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipv4": {"type": bool}, "ipv6": {"type": bool}, "threshold_minimum": {"type": int}, "_custom_data": {"type": dict}} + ipv4: bool | None + """Configure hardware offload for IPv4 traffic.""" + ipv6: bool | None + """Configure hardware offload for IPv6 traffic.""" + threshold_minimum: int | None + """Minimum number of samples.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4: bool | None | UndefinedType = Undefined, + ipv6: bool | None | UndefinedType = Undefined, + threshold_minimum: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + HardwareOffload. + + + Subclass of AvdModel. + + Args: + ipv4: Configure hardware offload for IPv4 traffic. + ipv6: Configure hardware offload for IPv6 traffic. + threshold_minimum: Minimum number of samples. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "encapsulation": {"type": Encapsulation}, + "sample": {"type": int, "default": 10000}, + "hardware_offload": {"type": HardwareOffload}, + "_custom_data": {"type": dict}, + } + encapsulation: Encapsulation + """Subclass of AvdModel.""" + sample: int + """Default value: `10000`""" + hardware_offload: HardwareOffload + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + encapsulation: Encapsulation | UndefinedType = Undefined, + sample: int | UndefinedType = Undefined, + hardware_offload: HardwareOffload | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Sampled. + + + Subclass of AvdModel. + + Args: + encapsulation: Subclass of AvdModel. + sample: sample + hardware_offload: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Hardware(AvdModel): + """Subclass of AvdModel.""" + + class Record(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"format_ipfix_standard_timestamps_counters": {"type": bool}, "_custom_data": {"type": dict}} + format_ipfix_standard_timestamps_counters: bool | None + """Enable software export of IPFIX data records.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + format_ipfix_standard_timestamps_counters: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Record. + + + Subclass of AvdModel. + + Args: + format_ipfix_standard_timestamps_counters: Enable software export of IPFIX data records. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"record": {"type": Record}, "_custom_data": {"type": dict}} + record: Record + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, record: Record | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Hardware. + + + Subclass of AvdModel. + + Args: + record: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class TrackersItem(AvdModel): + """Subclass of AvdModel.""" + + class Sampled(AvdModel): + """Subclass of AvdModel.""" + + class RecordExport(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"mpls": {"type": bool}, "_custom_data": {"type": dict}} + mpls: bool | None + """Export MPLS forwarding information.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, mpls: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + RecordExport. + + + Subclass of AvdModel. + + Args: + mpls: Export MPLS forwarding information. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"table_size": {"type": int}, "record_export": {"type": RecordExport}, "_custom_data": {"type": dict}} + table_size: int | None + """Maximum number of entries in flow table.""" + record_export: RecordExport + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + table_size: int | None | UndefinedType = Undefined, + record_export: RecordExport | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Sampled. + + + Subclass of AvdModel. + + Args: + table_size: Maximum number of entries in flow table. + record_export: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class RecordExport(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"on_inactive_timeout": {"type": int}, "on_interval": {"type": int}, "_custom_data": {"type": dict}} + on_inactive_timeout: int | None + """Flow record inactive export timeout in milliseconds""" + on_interval: int | None + """Flow record export interval in milliseconds""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + on_inactive_timeout: int | None | UndefinedType = Undefined, + on_interval: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RecordExport. + + + Subclass of AvdModel. + + Args: + on_inactive_timeout: Flow record inactive export timeout in milliseconds + on_interval: Flow record export interval in milliseconds + _custom_data: _custom_data + + """ + + class ExportersItem(AvdModel): + """Subclass of AvdModel.""" + + class Collector(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"host": {"type": str}, "port": {"type": int}, "_custom_data": {"type": dict}} + host: str | None + """Collector IPv4 address or IPv6 address or fully qualified domain name""" + port: int | None + """Collector Port Number""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + host: str | None | UndefinedType = Undefined, + port: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Collector. + + + Subclass of AvdModel. + + Args: + host: Collector IPv4 address or IPv6 address or fully qualified domain name + port: Collector Port Number + _custom_data: _custom_data + + """ + + class Format(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"ipfix_version": {"type": int}, "_custom_data": {"type": dict}} + ipfix_version: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, ipfix_version: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Format. + + + Subclass of AvdModel. + + Args: + ipfix_version: ipfix_version + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "collector": {"type": Collector}, + "format": {"type": Format}, + "local_interface": {"type": str}, + "template_interval": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str + """Exporter Name""" + collector: Collector + """Subclass of AvdModel.""" + format: Format + """Subclass of AvdModel.""" + local_interface: str | None + """Local Source Interface""" + template_interval: int | None + """Template interval in milliseconds""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + collector: Collector | UndefinedType = Undefined, + format: Format | UndefinedType = Undefined, + local_interface: str | None | UndefinedType = Undefined, + template_interval: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ExportersItem. + + + Subclass of AvdModel. + + Args: + name: Exporter Name + collector: Subclass of AvdModel. + format: Subclass of AvdModel. + local_interface: Local Source Interface + template_interval: Template interval in milliseconds + _custom_data: _custom_data + + """ + + class Exporters(AvdIndexedList[str, ExportersItem]): + """Subclass of AvdIndexedList with `ExportersItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Exporters._item_type = ExportersItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "sampled": {"type": Sampled}, + "record_export": {"type": RecordExport}, + "exporters": {"type": Exporters}, + "_custom_data": {"type": dict}, + } + name: str + """Tracker Name""" + sampled: Sampled + """ + The options relevant only for flow tracker type sampled. + + Subclass of AvdModel. + """ + record_export: RecordExport + """Subclass of AvdModel.""" + exporters: Exporters + """Subclass of AvdIndexedList with `ExportersItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + sampled: Sampled | UndefinedType = Undefined, + record_export: RecordExport | UndefinedType = Undefined, + exporters: Exporters | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TrackersItem. + + + Subclass of AvdModel. + + Args: + name: Tracker Name + sampled: + The options relevant only for flow tracker type sampled. + + Subclass of AvdModel. + record_export: Subclass of AvdModel. + exporters: Subclass of AvdIndexedList with `ExportersItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class Trackers(AvdIndexedList[str, TrackersItem]): + """Subclass of AvdIndexedList with `TrackersItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Trackers._item_type = TrackersItem + + _fields: ClassVar[dict] = { + "sampled": {"type": Sampled}, + "hardware": {"type": Hardware}, + "trackers": { + "type": Trackers, + "default": lambda cls: coerce_type( + [ + { + "name": "FLOW-TRACKER", + "record_export": {"on_inactive_timeout": 70000, "on_interval": 300000}, + "exporters": [ + {"name": "CV-TELEMETRY", "collector": {"host": "127.0.0.1"}, "local_interface": "Loopback0", "template_interval": 3600000} + ], + } + ], + target_type=cls, + ), + }, + "_custom_data": {"type": dict}, + } + sampled: Sampled + """ + The options relevant only for flow tracker type sampled. + + Subclass of AvdModel. + """ + hardware: Hardware + """ + The options relevant only for flow tracker type hardware. + + Subclass of AvdModel. + """ + trackers: Trackers + """ + Subclass of AvdIndexedList with `TrackersItem` items. Primary key is `name` (`str`). + + Default value: `lambda cls: coerce_type([{"name": "FLOW-TRACKER", "record_export": {"on_inactive_timeout": 70000, "on_interval": 300000}, "exporters": [{"name": "CV-TELEMETRY", "collector": {"host": "127.0.0.1"}, "local_interface": "Loopback0", "template_interval": 3600000}]}], target_type=cls)` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sampled: Sampled | UndefinedType = Undefined, + hardware: Hardware | UndefinedType = Undefined, + trackers: Trackers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTrackingSettings. + + + Subclass of AvdModel. + + Args: + sampled: + The options relevant only for flow tracker type sampled. + + Subclass of AvdModel. + hardware: + The options relevant only for flow tracker type hardware. + + Subclass of AvdModel. + trackers: Subclass of AvdIndexedList with `TrackersItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class GenerateCvTags(AvdModel): + """Subclass of AvdModel.""" + + class InterfaceTagsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "data_path": {"type": str}, "value": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Tag name to be assigned to generated tags.""" + data_path: str | None + """ + Structured config field/key path to be used to find the value for the tag. Dot notation is supported + to reference values inside dictionaries. + For Example: 'data_path: channel_group.id' would set the + tag with the value of the channel id of the interface. If there is no channel id, the tag is not + created. + `data_path` is ignored if `value` is set. + """ + value: str | None + """Value to be assigned to the tag.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + data_path: str | None | UndefinedType = Undefined, + value: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + InterfaceTagsItem. + + + Subclass of AvdModel. + + Args: + name: Tag name to be assigned to generated tags. + data_path: + Structured config field/key path to be used to find the value for the tag. Dot notation is supported + to reference values inside dictionaries. + For Example: 'data_path: channel_group.id' would set the + tag with the value of the channel id of the interface. If there is no channel id, the tag is not + created. + `data_path` is ignored if `value` is set. + value: Value to be assigned to the tag. + _custom_data: _custom_data + + """ + + class InterfaceTags(AvdIndexedList[str, InterfaceTagsItem]): + """Subclass of AvdIndexedList with `InterfaceTagsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + InterfaceTags._item_type = InterfaceTagsItem + + class DeviceTagsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "data_path": {"type": str}, "value": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Tag name to be assigned to generated tags.""" + data_path: str | None + """ + Structured config field/key path to be used to find the value for the tag. Dot notation is supported + to reference values inside dictionaries. + For Example: 'data_path: router_bfd.multihop.interval' + would set the tag with the value of the interval for multihop bfd. If this value is not specified in + the structured config, the tag is not created. + `data_path` is ignored if `value` is set. + """ + value: str | None + """Value to be assigned to the tag.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + data_path: str | None | UndefinedType = Undefined, + value: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DeviceTagsItem. + + + Subclass of AvdModel. + + Args: + name: Tag name to be assigned to generated tags. + data_path: + Structured config field/key path to be used to find the value for the tag. Dot notation is supported + to reference values inside dictionaries. + For Example: 'data_path: router_bfd.multihop.interval' + would set the tag with the value of the interval for multihop bfd. If this value is not specified in + the structured config, the tag is not created. + `data_path` is ignored if `value` is set. + value: Value to be assigned to the tag. + _custom_data: _custom_data + + """ + + class DeviceTags(AvdList[DeviceTagsItem]): + """Subclass of AvdList with `DeviceTagsItem` items.""" + + DeviceTags._item_type = DeviceTagsItem + + _fields: ClassVar[dict] = { + "topology_hints": {"type": bool, "default": False}, + "interface_tags": {"type": InterfaceTags}, + "device_tags": {"type": DeviceTags}, + "_custom_data": {"type": dict}, + } + topology_hints: bool + """ + Enable the generation of CloudVision Topology Tags (hints). + + Default value: `False` + """ + interface_tags: InterfaceTags + """ + List of interface tags that should be generated. + + Subclass of AvdIndexedList with + `InterfaceTagsItem` items. Primary key is `name` (`str`). + """ + device_tags: DeviceTags + """ + List of device tags that should be generated. + + Subclass of AvdList with `DeviceTagsItem` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + topology_hints: bool | UndefinedType = Undefined, + interface_tags: InterfaceTags | UndefinedType = Undefined, + device_tags: DeviceTags | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GenerateCvTags. + + + Subclass of AvdModel. + + Args: + topology_hints: Enable the generation of CloudVision Topology Tags (hints). + interface_tags: + List of interface tags that should be generated. + + Subclass of AvdIndexedList with + `InterfaceTagsItem` items. Primary key is `name` (`str`). + device_tags: + List of device tags that should be generated. + + Subclass of AvdList with `DeviceTagsItem` items. + _custom_data: _custom_data + + """ + + class HardwareCounters(EosCliConfigGen.HardwareCounters): + """Subclass of AvdModel.""" + + class InternalVlanOrder(AvdModel): + """Subclass of AvdModel.""" + + class Range(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"beginning": {"type": int}, "ending": {"type": int}, "_custom_data": {"type": dict}} + beginning: int + """First VLAN ID.""" + ending: int + """Last VLAN ID.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + beginning: int | UndefinedType = Undefined, + ending: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Range. + + + Subclass of AvdModel. + + Args: + beginning: First VLAN ID. + ending: Last VLAN ID. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"allocation": {"type": str}, "range": {"type": Range}, "_custom_data": {"type": dict}} + allocation: Literal["ascending", "descending"] + range: Range + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + allocation: Literal["ascending", "descending"] | UndefinedType = Undefined, + range: Range | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + InternalVlanOrder. + + + Subclass of AvdModel. + + Args: + allocation: allocation + range: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Ipv4AclsItem(AvdModel): + """Subclass of AvdModel.""" + + class EntriesItem(AvdModel): + """Subclass of AvdModel.""" + + class SourcePorts(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + SourcePorts._item_type = str + + class DestinationPorts(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DestinationPorts._item_type = str + + class TcpFlags(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + TcpFlags._item_type = str + + _fields: ClassVar[dict] = { + "source": {"type": str}, + "destination": {"type": str}, + "sequence": {"type": int}, + "remark": {"type": str}, + "action": {"type": str}, + "protocol": {"type": str}, + "source_ports_match": {"type": str, "default": "eq"}, + "source_ports": {"type": SourcePorts}, + "destination_ports_match": {"type": str, "default": "eq"}, + "destination_ports": {"type": DestinationPorts}, + "tcp_flags": {"type": TcpFlags}, + "fragments": {"type": bool}, + "log": {"type": bool}, + "ttl": {"type": int}, + "ttl_match": {"type": str, "default": "eq"}, + "icmp_type": {"type": str}, + "icmp_code": {"type": str}, + "nexthop_group": {"type": str}, + "tracked": {"type": bool}, + "dscp": {"type": str}, + "vlan_number": {"type": int}, + "vlan_inner": {"type": bool, "default": False}, + "vlan_mask": {"type": str}, + "_custom_data": {"type": dict}, + } + source: str | None + """ + This field supports substitution of the fields "interface_ip" for SVIs and both "interface_ip" and + "peer_ip" for Layer 3 interfaces. + Alternatively it can be set with a static value of "any", + "/" or "". + "" without a mask means host. + Required except for remarks. + """ + destination: str | None + """ + This field supports substitution of the fields "interface_ip" for SVIs and both "interface_ip" and + "peer_ip" for Layer 3 interfaces. + Alternatively it can be set with a static value of "any", + "/" or "". + "" without a mask means host. + Required except for remarks. + """ + sequence: int | None + """ACL entry sequence number.""" + remark: str | None + """ + Comment up to 100 characters. + If remark is defined, other keys in the ACL entry will be ignored. + """ + action: Literal["permit", "deny"] | None + """ + ACL action. + Required except for remarks. + """ + protocol: str | None + """ + "ip", "tcp", "udp", "icmp" or other protocol name or number. + Required except for remarks. + """ + source_ports_match: Literal["eq", "gt", "lt", "neq", "range"] + """Default value: `"eq"`""" + source_ports: SourcePorts + """Subclass of AvdList with `str` items.""" + destination_ports_match: Literal["eq", "gt", "lt", "neq", "range"] + """Default value: `"eq"`""" + destination_ports: DestinationPorts + """Subclass of AvdList with `str` items.""" + tcp_flags: TcpFlags + """Subclass of AvdList with `str` items.""" + fragments: bool | None + """Match non-head fragment packets.""" + log: bool | None + """Log matches against this rule.""" + ttl: int | None + """TTL value.""" + ttl_match: Literal["eq", "gt", "lt", "neq"] + """Default value: `"eq"`""" + icmp_type: str | None + """Message type name/number for ICMP packets.""" + icmp_code: str | None + """Message code for ICMP packets.""" + nexthop_group: str | None + """nexthop-group name.""" + tracked: bool | None + """Match packets in existing ICMP/UDP/TCP connections.""" + dscp: str | None + """DSCP value or name.""" + vlan_number: int | None + vlan_inner: bool + """Default value: `False`""" + vlan_mask: str | None + """0x000-0xFFF VLAN mask.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + source: str | None | UndefinedType = Undefined, + destination: str | None | UndefinedType = Undefined, + sequence: int | None | UndefinedType = Undefined, + remark: str | None | UndefinedType = Undefined, + action: Literal["permit", "deny"] | None | UndefinedType = Undefined, + protocol: str | None | UndefinedType = Undefined, + source_ports_match: Literal["eq", "gt", "lt", "neq", "range"] | UndefinedType = Undefined, + source_ports: SourcePorts | UndefinedType = Undefined, + destination_ports_match: Literal["eq", "gt", "lt", "neq", "range"] | UndefinedType = Undefined, + destination_ports: DestinationPorts | UndefinedType = Undefined, + tcp_flags: TcpFlags | UndefinedType = Undefined, + fragments: bool | None | UndefinedType = Undefined, + log: bool | None | UndefinedType = Undefined, + ttl: int | None | UndefinedType = Undefined, + ttl_match: Literal["eq", "gt", "lt", "neq"] | UndefinedType = Undefined, + icmp_type: str | None | UndefinedType = Undefined, + icmp_code: str | None | UndefinedType = Undefined, + nexthop_group: str | None | UndefinedType = Undefined, + tracked: bool | None | UndefinedType = Undefined, + dscp: str | None | UndefinedType = Undefined, + vlan_number: int | None | UndefinedType = Undefined, + vlan_inner: bool | UndefinedType = Undefined, + vlan_mask: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EntriesItem. + + + Subclass of AvdModel. + + Args: + source: + This field supports substitution of the fields "interface_ip" for SVIs and both "interface_ip" and + "peer_ip" for Layer 3 interfaces. + Alternatively it can be set with a static value of "any", + "/" or "". + "" without a mask means host. + Required except for remarks. + destination: + This field supports substitution of the fields "interface_ip" for SVIs and both "interface_ip" and + "peer_ip" for Layer 3 interfaces. + Alternatively it can be set with a static value of "any", + "/" or "". + "" without a mask means host. + Required except for remarks. + sequence: ACL entry sequence number. + remark: + Comment up to 100 characters. + If remark is defined, other keys in the ACL entry will be ignored. + action: + ACL action. + Required except for remarks. + protocol: + "ip", "tcp", "udp", "icmp" or other protocol name or number. + Required except for remarks. + source_ports_match: source_ports_match + source_ports: Subclass of AvdList with `str` items. + destination_ports_match: destination_ports_match + destination_ports: Subclass of AvdList with `str` items. + tcp_flags: Subclass of AvdList with `str` items. + fragments: Match non-head fragment packets. + log: Log matches against this rule. + ttl: TTL value. + ttl_match: ttl_match + icmp_type: Message type name/number for ICMP packets. + icmp_code: Message code for ICMP packets. + nexthop_group: nexthop-group name. + tracked: Match packets in existing ICMP/UDP/TCP connections. + dscp: DSCP value or name. + vlan_number: vlan_number + vlan_inner: vlan_inner + vlan_mask: 0x000-0xFFF VLAN mask. + _custom_data: _custom_data + + """ + + class Entries(AvdList[EntriesItem]): + """Subclass of AvdList with `EntriesItem` items.""" + + Entries._item_type = EntriesItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "entries": {"type": Entries}, + "counters_per_entry": {"type": bool}, + "permit_response_traffic": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """ + Access-list name. + When using substitution for any fields, the interface name will be appended to the + ACL name. + """ + entries: Entries + """ + ACL Entries. + + Subclass of AvdList with `EntriesItem` items. + """ + counters_per_entry: bool | None + permit_response_traffic: Literal["nat"] | None + """ + Permit response traffic automatically based on NAT translations. + Minimum EOS version requirement + 4.32.2F. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + entries: Entries | UndefinedType = Undefined, + counters_per_entry: bool | None | UndefinedType = Undefined, + permit_response_traffic: Literal["nat"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4AclsItem. + + + Subclass of AvdModel. + + Args: + name: + Access-list name. + When using substitution for any fields, the interface name will be appended to the + ACL name. + entries: + ACL Entries. + + Subclass of AvdList with `EntriesItem` items. + counters_per_entry: counters_per_entry + permit_response_traffic: + Permit response traffic automatically based on NAT translations. + Minimum EOS version requirement + 4.32.2F. + _custom_data: _custom_data + + """ + + class Ipv4Acls(AvdIndexedList[str, Ipv4AclsItem]): + """Subclass of AvdIndexedList with `Ipv4AclsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Ipv4Acls._item_type = Ipv4AclsItem + + class Ipv4PrefixListCatalogItem(AvdModel): + """Subclass of AvdModel.""" + + class SequenceNumbersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"sequence": {"type": int}, "action": {"type": str}, "_custom_data": {"type": dict}} + sequence: int + """Sequence ID.""" + action: str + """ + Action as string. + Example: "permit 10.255.0.0/27 eq 32" + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sequence: int | UndefinedType = Undefined, + action: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceNumbersItem. + + + Subclass of AvdModel. + + Args: + sequence: Sequence ID. + action: + Action as string. + Example: "permit 10.255.0.0/27 eq 32" + _custom_data: _custom_data + + """ + + class SequenceNumbers(AvdIndexedList[int, SequenceNumbersItem]): + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + + _primary_key: ClassVar[str] = "sequence" + + SequenceNumbers._item_type = SequenceNumbersItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "sequence_numbers": {"type": SequenceNumbers}, "_custom_data": {"type": dict}} + name: str + """Prefix-list Name.""" + sequence_numbers: SequenceNumbers + """Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + sequence_numbers: SequenceNumbers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4PrefixListCatalogItem. + + + Subclass of AvdModel. + + Args: + name: Prefix-list Name. + sequence_numbers: Subclass of AvdIndexedList with `SequenceNumbersItem` items. Primary key is `sequence` (`int`). + _custom_data: _custom_data + + """ + + class Ipv4PrefixListCatalog(AvdIndexedList[str, Ipv4PrefixListCatalogItem]): + """Subclass of AvdIndexedList with `Ipv4PrefixListCatalogItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Ipv4PrefixListCatalog._item_type = Ipv4PrefixListCatalogItem + + class Ipv6MgmtDestinationNetworks(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Ipv6MgmtDestinationNetworks._item_type = str + + class IsisTiLfa(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "protection": {"type": str}, + "local_convergence_delay": {"type": int, "default": 10000}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + protection: Literal["link", "node"] | None + local_convergence_delay: int + """ + Local convergence delay in milliseconds. + + Default value: `10000` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + protection: Literal["link", "node"] | None | UndefinedType = Undefined, + local_convergence_delay: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IsisTiLfa. + + + Subclass of AvdModel. + + Args: + enabled: enabled + protection: protection + local_convergence_delay: Local convergence delay in milliseconds. + _custom_data: _custom_data + + """ + + class L3Edge(AvdModel): + """Subclass of AvdModel.""" + + class P2pLinksIpPoolsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "ipv4_pool": {"type": str}, + "prefix_size": {"type": int, "default": 31}, + "_custom_data": {"type": dict}, + } + name: str + """P2P pool name.""" + ipv4_pool: str | None + """IPv4 address/Mask.""" + prefix_size: int + """ + Subnet mask size. + + Default value: `31` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + ipv4_pool: str | None | UndefinedType = Undefined, + prefix_size: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + P2pLinksIpPoolsItem. + + + Subclass of AvdModel. + + Args: + name: P2P pool name. + ipv4_pool: IPv4 address/Mask. + prefix_size: Subnet mask size. + _custom_data: _custom_data + + """ + + class P2pLinksIpPools(AvdIndexedList[str, P2pLinksIpPoolsItem]): + """Subclass of AvdIndexedList with `P2pLinksIpPoolsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + P2pLinksIpPools._item_type = P2pLinksIpPoolsItem + + class P2pLinksProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class Ip(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Ip._item_type = str + + class Nodes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Nodes._item_type = str + + class Interfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Interfaces._item_type = str + + class As(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + As._item_type = str + + class Descriptions(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Descriptions._item_type = str + + class Ptp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enabled: bool + """ + Enable PTP. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, enabled: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Ptp. + + + Subclass of AvdModel. + + Args: + enabled: Enable PTP. + _custom_data: _custom_data + + """ + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class PortChannel(AvdModel): + """Subclass of AvdModel.""" + + class NodesChildInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Interfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Interfaces._item_type = str + + _fields: ClassVar[dict] = { + "node": {"type": str}, + "interfaces": {"type": Interfaces}, + "channel_id": {"type": int}, + "_custom_data": {"type": dict}, + } + node: str + interfaces: Interfaces + """ + List of node interfaces. Ex.- [ 'node1 interface1', 'node1 interface2' ]. + + Subclass of AvdList with + `str` items. + """ + channel_id: int | None + """ + Port-Channel ID. If no channel_id is specified, an id is generated from the first switch port in the + port channel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + node: str | UndefinedType = Undefined, + interfaces: Interfaces | UndefinedType = Undefined, + channel_id: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NodesChildInterfacesItem. + + + Subclass of AvdModel. + + Args: + node: node + interfaces: + List of node interfaces. Ex.- [ 'node1 interface1', 'node1 interface2' ]. + + Subclass of AvdList with + `str` items. + channel_id: + Port-Channel ID. If no channel_id is specified, an id is generated from the first switch port in the + port channel. + _custom_data: _custom_data + + """ + + class NodesChildInterfaces(AvdIndexedList[str, NodesChildInterfacesItem]): + """Subclass of AvdIndexedList with `NodesChildInterfacesItem` items. Primary key is `node` (`str`).""" + + _primary_key: ClassVar[str] = "node" + + NodesChildInterfaces._item_type = NodesChildInterfacesItem + + _fields: ClassVar[dict] = { + "description": {"type": str}, + "mode": {"type": str, "default": "active"}, + "nodes_child_interfaces": {"type": NodesChildInterfaces}, + "_custom_data": {"type": dict}, + } + description: str | None + """ + Description or description template to be used on the port-channel interface. + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `peer`: The name of the peer. + - `interface`: The local port-channel interface name. + - + `peer_interface`: The port-channel interface on the peer. + - `port_channel_id`: The local port- + channel ID. + - `peer_port_channel_id`: The ID of the port-channel on the peer. + + Falls back to the + description on the `p2p_link` if set. Otherwise default description is set by + `default_underlay_p2p_port_channel_description`. + By default the description is templated from the + name and port_channel interface of the peer. + """ + mode: str + """Default value: `"active"`""" + nodes_child_interfaces: NodesChildInterfaces + """Subclass of AvdIndexedList with `NodesChildInterfacesItem` items. Primary key is `node` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + description: str | None | UndefinedType = Undefined, + mode: str | UndefinedType = Undefined, + nodes_child_interfaces: NodesChildInterfaces | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PortChannel. + + + Subclass of AvdModel. + + Args: + description: + Description or description template to be used on the port-channel interface. + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `peer`: The name of the peer. + - `interface`: The local port-channel interface name. + - + `peer_interface`: The port-channel interface on the peer. + - `port_channel_id`: The local port- + channel ID. + - `peer_port_channel_id`: The ID of the port-channel on the peer. + + Falls back to the + description on the `p2p_link` if set. Otherwise default description is set by + `default_underlay_p2p_port_channel_description`. + By default the description is templated from the + name and port_channel interface of the peer. + mode: mode + nodes_child_interfaces: Subclass of AvdIndexedList with `NodesChildInterfacesItem` items. Primary key is `node` (`str`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "id": {"type": int}, + "speed": {"type": str}, + "ip_pool": {"type": str}, + "subnet": {"type": str}, + "ip": {"type": Ip}, + "ipv6_enable": {"type": bool, "default": False}, + "nodes": {"type": Nodes}, + "interfaces": {"type": Interfaces}, + "field_as": {"type": As}, + "descriptions": {"type": Descriptions}, + "include_in_underlay_protocol": {"type": bool, "default": True}, + "isis_hello_padding": {"type": bool, "default": True}, + "isis_metric": {"type": int}, + "isis_circuit_type": {"type": str}, + "isis_authentication_mode": {"type": str}, + "isis_authentication_key": {"type": str}, + "isis_network_type": {"type": str, "default": "point-to-point"}, + "mpls_ip": {"type": bool}, + "mpls_ldp": {"type": bool}, + "mtu": {"type": int}, + "bfd": {"type": bool}, + "ptp": {"type": Ptp}, + "sflow": {"type": bool}, + "underlay_multicast": {"type": bool, "default": False}, + "flow_tracking": {"type": FlowTracking}, + "qos_profile": {"type": str}, + "macsec_profile": {"type": str}, + "port_channel": {"type": PortChannel}, + "raw_eos_cli": {"type": str}, + "routing_protocol": {"type": str}, + "structured_config": {"type": dict}, + "_custom_data": {"type": dict}, + } + _field_to_key_map: ClassVar[dict] = {"field_as": "as"} + _key_to_field_map: ClassVar[dict] = {"as": "field_as"} + name: str + """P2P profile name. Any variable supported under `p2p_links` can be inherited from a profile.""" + id: int | None + """ + Unique id per subnet_summary. Used to calculate ip addresses. + Required with ip_pool. ID starting + from 1. + """ + speed: str | None + """ + Speed should be set in the format `` or `forced ` or `auto + `. + """ + ip_pool: str | None + """ + P2P pool name. IP Pool defined under p2p_links_ip_pools. A /31 will be taken from the pool per P2P + link. + """ + subnet: str | None + """IPv4 address/Mask. Subnet used on this P2P link.""" + ip: Ip + """ + Specific IP addresses used on this P2P link. + + Subclass of AvdList with `str` items. + """ + ipv6_enable: bool + """ + Allows turning on ipv6 for the link or profile (also autodetected based on underlay_rfc5549 and + include_in_underlay_protocol). + + Default value: `False` + """ + nodes: Nodes + """ + Nodes where this link should be configured. + + Subclass of AvdList with `str` items. + """ + interfaces: Interfaces + """ + Interfaces where this link should be configured and Required unless using port-channels. + + Subclass + of AvdList with `str` items. + """ + field_as: As + """ + AS numbers for BGP. + Required with bgp peering. + + + Subclass of AvdList with `str` items. + """ + descriptions: Descriptions + """ + Interface descriptions. + + Subclass of AvdList with `str` items. + """ + include_in_underlay_protocol: bool + """ + Add this interface to underlay routing protocol. + + Default value: `True` + """ + isis_hello_padding: bool + """Default value: `True`""" + isis_metric: int | None + isis_circuit_type: Literal["level-1", "level-2", "level-1-2"] | None + isis_authentication_mode: Literal["md5", "text"] | None + isis_authentication_key: str | None + """Type-7 encrypted password.""" + isis_network_type: Literal["point-to-point", "broadcast"] + """Default value: `"point-to-point"`""" + mpls_ip: bool | None + """MPLS parameters. Default value is true if switch.mpls_lsr is true.""" + mpls_ldp: bool | None + """MPLS parameters. Default value is true for ldp underlay variants, otherwise false.""" + mtu: int | None + """MTU for this P2P link. Default value same as p2p_uplinks_mtu.""" + bfd: bool | None + """Enable BFD (only considered for BGP).""" + ptp: Ptp + """ + PTP parameters. + + Subclass of AvdModel. + """ + sflow: bool | None + """Enable sFlow. Overrides `fabric_sflow` setting.""" + underlay_multicast: bool + """ + Enable PIM sparse mode. Requires `include_in_underlay_protocol` and the global `underlay_multicast` + to be `true`. + + Default value: `False` + """ + flow_tracking: FlowTracking + """ + Enable flow-tracking. Overrides `fabric_flow_tracking` setting. + + Subclass of AvdModel. + """ + qos_profile: str | None + """QOS service profile.""" + macsec_profile: str | None + """MAC security profile.""" + port_channel: PortChannel + """ + Port-channel parameters. + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the point-to-point interface in the final EOS configuration.""" + routing_protocol: Literal["ebgp"] | None + """ + Enables deviation of the routing protocol used on this link from the fabric underlay default. + - + ebgp: Enforce plain IPv4 BGP peering + """ + structured_config: dict + """ + Custom structured config for interfaces. + Note! The content of this dictionary is _not_ validated by + the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + id: int | None | UndefinedType = Undefined, + speed: str | None | UndefinedType = Undefined, + ip_pool: str | None | UndefinedType = Undefined, + subnet: str | None | UndefinedType = Undefined, + ip: Ip | UndefinedType = Undefined, + ipv6_enable: bool | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + interfaces: Interfaces | UndefinedType = Undefined, + field_as: As | UndefinedType = Undefined, + descriptions: Descriptions | UndefinedType = Undefined, + include_in_underlay_protocol: bool | UndefinedType = Undefined, + isis_hello_padding: bool | UndefinedType = Undefined, + isis_metric: int | None | UndefinedType = Undefined, + isis_circuit_type: Literal["level-1", "level-2", "level-1-2"] | None | UndefinedType = Undefined, + isis_authentication_mode: Literal["md5", "text"] | None | UndefinedType = Undefined, + isis_authentication_key: str | None | UndefinedType = Undefined, + isis_network_type: Literal["point-to-point", "broadcast"] | UndefinedType = Undefined, + mpls_ip: bool | None | UndefinedType = Undefined, + mpls_ldp: bool | None | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + bfd: bool | None | UndefinedType = Undefined, + ptp: Ptp | UndefinedType = Undefined, + sflow: bool | None | UndefinedType = Undefined, + underlay_multicast: bool | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + qos_profile: str | None | UndefinedType = Undefined, + macsec_profile: str | None | UndefinedType = Undefined, + port_channel: PortChannel | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + routing_protocol: Literal["ebgp"] | None | UndefinedType = Undefined, + structured_config: dict | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + P2pLinksProfilesItem. + + + Subclass of AvdModel. + + Args: + name: P2P profile name. Any variable supported under `p2p_links` can be inherited from a profile. + id: + Unique id per subnet_summary. Used to calculate ip addresses. + Required with ip_pool. ID starting + from 1. + speed: + Speed should be set in the format `` or `forced ` or `auto + `. + ip_pool: + P2P pool name. IP Pool defined under p2p_links_ip_pools. A /31 will be taken from the pool per P2P + link. + subnet: IPv4 address/Mask. Subnet used on this P2P link. + ip: + Specific IP addresses used on this P2P link. + + Subclass of AvdList with `str` items. + ipv6_enable: + Allows turning on ipv6 for the link or profile (also autodetected based on underlay_rfc5549 and + include_in_underlay_protocol). + nodes: + Nodes where this link should be configured. + + Subclass of AvdList with `str` items. + interfaces: + Interfaces where this link should be configured and Required unless using port-channels. + + Subclass + of AvdList with `str` items. + field_as: + AS numbers for BGP. + Required with bgp peering. + + + Subclass of AvdList with `str` items. + descriptions: + Interface descriptions. + + Subclass of AvdList with `str` items. + include_in_underlay_protocol: Add this interface to underlay routing protocol. + isis_hello_padding: isis_hello_padding + isis_metric: isis_metric + isis_circuit_type: isis_circuit_type + isis_authentication_mode: isis_authentication_mode + isis_authentication_key: Type-7 encrypted password. + isis_network_type: isis_network_type + mpls_ip: MPLS parameters. Default value is true if switch.mpls_lsr is true. + mpls_ldp: MPLS parameters. Default value is true for ldp underlay variants, otherwise false. + mtu: MTU for this P2P link. Default value same as p2p_uplinks_mtu. + bfd: Enable BFD (only considered for BGP). + ptp: + PTP parameters. + + Subclass of AvdModel. + sflow: Enable sFlow. Overrides `fabric_sflow` setting. + underlay_multicast: + Enable PIM sparse mode. Requires `include_in_underlay_protocol` and the global `underlay_multicast` + to be `true`. + flow_tracking: + Enable flow-tracking. Overrides `fabric_flow_tracking` setting. + + Subclass of AvdModel. + qos_profile: QOS service profile. + macsec_profile: MAC security profile. + port_channel: + Port-channel parameters. + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the point-to-point interface in the final EOS configuration. + routing_protocol: + Enables deviation of the routing protocol used on this link from the fabric underlay default. + - + ebgp: Enforce plain IPv4 BGP peering + structured_config: + Custom structured config for interfaces. + Note! The content of this dictionary is _not_ validated by + the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + _custom_data: _custom_data + + """ + + class P2pLinksProfiles(AvdIndexedList[str, P2pLinksProfilesItem]): + """Subclass of AvdIndexedList with `P2pLinksProfilesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + P2pLinksProfiles._item_type = P2pLinksProfilesItem + + class P2pLinksItem(AvdModel): + """Subclass of AvdModel.""" + + class Nodes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Nodes._item_type = str + + class Ip(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Ip._item_type = str + + class Interfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Interfaces._item_type = str + + class As(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + As._item_type = str + + class Descriptions(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Descriptions._item_type = str + + class Ptp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enabled: bool + """ + Enable PTP. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, enabled: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Ptp. + + + Subclass of AvdModel. + + Args: + enabled: Enable PTP. + _custom_data: _custom_data + + """ + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class PortChannel(AvdModel): + """Subclass of AvdModel.""" + + class NodesChildInterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Interfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Interfaces._item_type = str + + _fields: ClassVar[dict] = { + "node": {"type": str}, + "interfaces": {"type": Interfaces}, + "channel_id": {"type": int}, + "_custom_data": {"type": dict}, + } + node: str + interfaces: Interfaces + """ + List of node interfaces. Ex.- [ 'node1 interface1', 'node1 interface2' ]. + + Subclass of AvdList with + `str` items. + """ + channel_id: int | None + """ + Port-Channel ID. If no channel_id is specified, an id is generated from the first switch port in the + port channel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + node: str | UndefinedType = Undefined, + interfaces: Interfaces | UndefinedType = Undefined, + channel_id: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NodesChildInterfacesItem. + + + Subclass of AvdModel. + + Args: + node: node + interfaces: + List of node interfaces. Ex.- [ 'node1 interface1', 'node1 interface2' ]. + + Subclass of AvdList with + `str` items. + channel_id: + Port-Channel ID. If no channel_id is specified, an id is generated from the first switch port in the + port channel. + _custom_data: _custom_data + + """ + + class NodesChildInterfaces(AvdIndexedList[str, NodesChildInterfacesItem]): + """Subclass of AvdIndexedList with `NodesChildInterfacesItem` items. Primary key is `node` (`str`).""" + + _primary_key: ClassVar[str] = "node" + + NodesChildInterfaces._item_type = NodesChildInterfacesItem + + _fields: ClassVar[dict] = { + "description": {"type": str}, + "mode": {"type": str, "default": "active"}, + "nodes_child_interfaces": {"type": NodesChildInterfaces}, + "_custom_data": {"type": dict}, + } + description: str | None + """ + Description or description template to be used on the port-channel interface. + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `peer`: The name of the peer. + - `interface`: The local port-channel interface name. + - + `peer_interface`: The port-channel interface on the peer. + - `port_channel_id`: The local port- + channel ID. + - `peer_port_channel_id`: The ID of the port-channel on the peer. + + Falls back to the + description on the `p2p_link` if set. Otherwise default description is set by + `default_underlay_p2p_port_channel_description`. + By default the description is templated from the + name and port_channel interface of the peer. + """ + mode: str + """Default value: `"active"`""" + nodes_child_interfaces: NodesChildInterfaces + """Subclass of AvdIndexedList with `NodesChildInterfacesItem` items. Primary key is `node` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + description: str | None | UndefinedType = Undefined, + mode: str | UndefinedType = Undefined, + nodes_child_interfaces: NodesChildInterfaces | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PortChannel. + + + Subclass of AvdModel. + + Args: + description: + Description or description template to be used on the port-channel interface. + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `peer`: The name of the peer. + - `interface`: The local port-channel interface name. + - + `peer_interface`: The port-channel interface on the peer. + - `port_channel_id`: The local port- + channel ID. + - `peer_port_channel_id`: The ID of the port-channel on the peer. + + Falls back to the + description on the `p2p_link` if set. Otherwise default description is set by + `default_underlay_p2p_port_channel_description`. + By default the description is templated from the + name and port_channel interface of the peer. + mode: mode + nodes_child_interfaces: Subclass of AvdIndexedList with `NodesChildInterfacesItem` items. Primary key is `node` (`str`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "nodes": {"type": Nodes}, + "profile": {"type": str}, + "id": {"type": int}, + "speed": {"type": str}, + "ip_pool": {"type": str}, + "subnet": {"type": str}, + "ip": {"type": Ip}, + "ipv6_enable": {"type": bool, "default": False}, + "interfaces": {"type": Interfaces}, + "field_as": {"type": As}, + "descriptions": {"type": Descriptions}, + "include_in_underlay_protocol": {"type": bool, "default": True}, + "isis_hello_padding": {"type": bool, "default": True}, + "isis_metric": {"type": int}, + "isis_circuit_type": {"type": str}, + "isis_authentication_mode": {"type": str}, + "isis_authentication_key": {"type": str}, + "isis_network_type": {"type": str, "default": "point-to-point"}, + "mpls_ip": {"type": bool}, + "mpls_ldp": {"type": bool}, + "mtu": {"type": int}, + "bfd": {"type": bool}, + "ptp": {"type": Ptp}, + "sflow": {"type": bool}, + "underlay_multicast": {"type": bool, "default": False}, + "flow_tracking": {"type": FlowTracking}, + "qos_profile": {"type": str}, + "macsec_profile": {"type": str}, + "port_channel": {"type": PortChannel}, + "raw_eos_cli": {"type": str}, + "routing_protocol": {"type": str}, + "structured_config": {"type": dict}, + "_custom_data": {"type": dict}, + } + _field_to_key_map: ClassVar[dict] = {"field_as": "as"} + _key_to_field_map: ClassVar[dict] = {"as": "field_as"} + nodes: Nodes + """ + Nodes where this link should be configured. + + Subclass of AvdList with `str` items. + """ + profile: str | None + """P2P profile name. Profile defined under p2p_profiles.""" + id: int | None + """ + Unique id per subnet_summary. Used to calculate ip addresses. + Required with ip_pool. ID starting + from 1. + """ + speed: str | None + """ + Speed should be set in the format `` or `forced ` or `auto + `. + """ + ip_pool: str | None + """ + P2P pool name. IP Pool defined under p2p_links_ip_pools. A /31 will be taken from the pool per P2P + link. + """ + subnet: str | None + """IPv4 address/Mask. Subnet used on this P2P link.""" + ip: Ip + """ + Specific IP addresses used on this P2P link. + + Subclass of AvdList with `str` items. + """ + ipv6_enable: bool + """ + Allows turning on ipv6 for the link or profile (also autodetected based on underlay_rfc5549 and + include_in_underlay_protocol). + + Default value: `False` + """ + interfaces: Interfaces + """ + Interfaces where this link should be configured and Required unless using port-channels. + + Subclass + of AvdList with `str` items. + """ + field_as: As + """ + AS numbers for BGP. + Required with bgp peering. + + + Subclass of AvdList with `str` items. + """ + descriptions: Descriptions + """ + Interface descriptions. + + Subclass of AvdList with `str` items. + """ + include_in_underlay_protocol: bool + """ + Add this interface to underlay routing protocol. + + Default value: `True` + """ + isis_hello_padding: bool + """Default value: `True`""" + isis_metric: int | None + isis_circuit_type: Literal["level-1", "level-2", "level-1-2"] | None + isis_authentication_mode: Literal["md5", "text"] | None + isis_authentication_key: str | None + """Type-7 encrypted password.""" + isis_network_type: Literal["point-to-point", "broadcast"] + """Default value: `"point-to-point"`""" + mpls_ip: bool | None + """MPLS parameters. Default value is true if switch.mpls_lsr is true.""" + mpls_ldp: bool | None + """MPLS parameters. Default value is true for ldp underlay variants, otherwise false.""" + mtu: int | None + """MTU for this P2P link. Default value same as p2p_uplinks_mtu.""" + bfd: bool | None + """Enable BFD (only considered for BGP).""" + ptp: Ptp + """ + PTP parameters. + + Subclass of AvdModel. + """ + sflow: bool | None + """Enable sFlow. Overrides `fabric_sflow` setting.""" + underlay_multicast: bool + """ + Enable PIM sparse mode. Requires `include_in_underlay_protocol` and the global `underlay_multicast` + to be `true`. + + Default value: `False` + """ + flow_tracking: FlowTracking + """ + Enable flow-tracking. Overrides `fabric_flow_tracking` setting. + + Subclass of AvdModel. + """ + qos_profile: str | None + """QOS service profile.""" + macsec_profile: str | None + """MAC security profile.""" + port_channel: PortChannel + """ + Port-channel parameters. + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the point-to-point interface in the final EOS configuration.""" + routing_protocol: Literal["ebgp"] | None + """ + Enables deviation of the routing protocol used on this link from the fabric underlay default. + - + ebgp: Enforce plain IPv4 BGP peering + """ + structured_config: dict + """ + Custom structured config for interfaces. + Note! The content of this dictionary is _not_ validated by + the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + nodes: Nodes | UndefinedType = Undefined, + profile: str | None | UndefinedType = Undefined, + id: int | None | UndefinedType = Undefined, + speed: str | None | UndefinedType = Undefined, + ip_pool: str | None | UndefinedType = Undefined, + subnet: str | None | UndefinedType = Undefined, + ip: Ip | UndefinedType = Undefined, + ipv6_enable: bool | UndefinedType = Undefined, + interfaces: Interfaces | UndefinedType = Undefined, + field_as: As | UndefinedType = Undefined, + descriptions: Descriptions | UndefinedType = Undefined, + include_in_underlay_protocol: bool | UndefinedType = Undefined, + isis_hello_padding: bool | UndefinedType = Undefined, + isis_metric: int | None | UndefinedType = Undefined, + isis_circuit_type: Literal["level-1", "level-2", "level-1-2"] | None | UndefinedType = Undefined, + isis_authentication_mode: Literal["md5", "text"] | None | UndefinedType = Undefined, + isis_authentication_key: str | None | UndefinedType = Undefined, + isis_network_type: Literal["point-to-point", "broadcast"] | UndefinedType = Undefined, + mpls_ip: bool | None | UndefinedType = Undefined, + mpls_ldp: bool | None | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + bfd: bool | None | UndefinedType = Undefined, + ptp: Ptp | UndefinedType = Undefined, + sflow: bool | None | UndefinedType = Undefined, + underlay_multicast: bool | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + qos_profile: str | None | UndefinedType = Undefined, + macsec_profile: str | None | UndefinedType = Undefined, + port_channel: PortChannel | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + routing_protocol: Literal["ebgp"] | None | UndefinedType = Undefined, + structured_config: dict | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + P2pLinksItem. + + + Subclass of AvdModel. + + Args: + nodes: + Nodes where this link should be configured. + + Subclass of AvdList with `str` items. + profile: P2P profile name. Profile defined under p2p_profiles. + id: + Unique id per subnet_summary. Used to calculate ip addresses. + Required with ip_pool. ID starting + from 1. + speed: + Speed should be set in the format `` or `forced ` or `auto + `. + ip_pool: + P2P pool name. IP Pool defined under p2p_links_ip_pools. A /31 will be taken from the pool per P2P + link. + subnet: IPv4 address/Mask. Subnet used on this P2P link. + ip: + Specific IP addresses used on this P2P link. + + Subclass of AvdList with `str` items. + ipv6_enable: + Allows turning on ipv6 for the link or profile (also autodetected based on underlay_rfc5549 and + include_in_underlay_protocol). + interfaces: + Interfaces where this link should be configured and Required unless using port-channels. + + Subclass + of AvdList with `str` items. + field_as: + AS numbers for BGP. + Required with bgp peering. + + + Subclass of AvdList with `str` items. + descriptions: + Interface descriptions. + + Subclass of AvdList with `str` items. + include_in_underlay_protocol: Add this interface to underlay routing protocol. + isis_hello_padding: isis_hello_padding + isis_metric: isis_metric + isis_circuit_type: isis_circuit_type + isis_authentication_mode: isis_authentication_mode + isis_authentication_key: Type-7 encrypted password. + isis_network_type: isis_network_type + mpls_ip: MPLS parameters. Default value is true if switch.mpls_lsr is true. + mpls_ldp: MPLS parameters. Default value is true for ldp underlay variants, otherwise false. + mtu: MTU for this P2P link. Default value same as p2p_uplinks_mtu. + bfd: Enable BFD (only considered for BGP). + ptp: + PTP parameters. + + Subclass of AvdModel. + sflow: Enable sFlow. Overrides `fabric_sflow` setting. + underlay_multicast: + Enable PIM sparse mode. Requires `include_in_underlay_protocol` and the global `underlay_multicast` + to be `true`. + flow_tracking: + Enable flow-tracking. Overrides `fabric_flow_tracking` setting. + + Subclass of AvdModel. + qos_profile: QOS service profile. + macsec_profile: MAC security profile. + port_channel: + Port-channel parameters. + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the point-to-point interface in the final EOS configuration. + routing_protocol: + Enables deviation of the routing protocol used on this link from the fabric underlay default. + - + ebgp: Enforce plain IPv4 BGP peering + structured_config: + Custom structured config for interfaces. + Note! The content of this dictionary is _not_ validated by + the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + _custom_data: _custom_data + + """ + + class P2pLinks(AvdList[P2pLinksItem]): + """Subclass of AvdList with `P2pLinksItem` items.""" + + P2pLinks._item_type = P2pLinksItem + + _fields: ClassVar[dict] = { + "p2p_links_ip_pools": {"type": P2pLinksIpPools}, + "p2p_links_profiles": {"type": P2pLinksProfiles}, + "p2p_links": {"type": P2pLinks}, + "_custom_data": {"type": dict}, + } + p2p_links_ip_pools: P2pLinksIpPools + """Subclass of AvdIndexedList with `P2pLinksIpPoolsItem` items. Primary key is `name` (`str`).""" + p2p_links_profiles: P2pLinksProfiles + """Subclass of AvdIndexedList with `P2pLinksProfilesItem` items. Primary key is `name` (`str`).""" + p2p_links: P2pLinks + """Subclass of AvdList with `P2pLinksItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + p2p_links_ip_pools: P2pLinksIpPools | UndefinedType = Undefined, + p2p_links_profiles: P2pLinksProfiles | UndefinedType = Undefined, + p2p_links: P2pLinks | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L3Edge. + + + Subclass of AvdModel. + + Args: + p2p_links_ip_pools: Subclass of AvdIndexedList with `P2pLinksIpPoolsItem` items. Primary key is `name` (`str`). + p2p_links_profiles: Subclass of AvdIndexedList with `P2pLinksProfilesItem` items. Primary key is `name` (`str`). + p2p_links: Subclass of AvdList with `P2pLinksItem` items. + _custom_data: _custom_data + + """ + + class L3InterfaceProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "peer_as": {"type": str}, + "ipv4_prefix_list_in": {"type": str}, + "ipv4_prefix_list_out": {"type": str}, + "_custom_data": {"type": dict}, + } + peer_as: str + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + ipv4_prefix_list_in: str | None + """ + Prefix List Name. Accept routes for only these prefixes from the peer. + Required for wan interfaces. + """ + ipv4_prefix_list_out: str | None + """ + Prefix List Name. Advertise routes for only these prefixes. + If not specified, nothing would be + advertised. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + peer_as: str | UndefinedType = Undefined, + ipv4_prefix_list_in: str | None | UndefinedType = Undefined, + ipv4_prefix_list_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + peer_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + ipv4_prefix_list_in: + Prefix List Name. Accept routes for only these prefixes from the peer. + Required for wan interfaces. + ipv4_prefix_list_out: + Prefix List Name. Advertise routes for only these prefixes. + If not specified, nothing would be + advertised. + _custom_data: _custom_data + + """ + + class StaticRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "_custom_data": {"type": dict}} + prefix: str + """IPv4_network/Mask.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, prefix: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + StaticRoutesItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv4_network/Mask. + _custom_data: _custom_data + + """ + + class StaticRoutes(AvdList[StaticRoutesItem]): + """Subclass of AvdList with `StaticRoutesItem` items.""" + + StaticRoutes._item_type = StaticRoutesItem + + class CvPathfinderInternetExit(AvdModel): + """Subclass of AvdModel.""" + + class PoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "tunnel_interface_numbers": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Internet-exit policy name.""" + tunnel_interface_numbers: str | None + """ + Number range to use for Tunnel interfaces to an internet-exit service provider using this local + interface. + Examples: '1-3' or '100,200,300' + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + tunnel_interface_numbers: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PoliciesItem. + + + Subclass of AvdModel. + + Args: + name: Internet-exit policy name. + tunnel_interface_numbers: + Number range to use for Tunnel interfaces to an internet-exit service provider using this local + interface. + Examples: '1-3' or '100,200,300' + _custom_data: _custom_data + + """ + + class Policies(AvdIndexedList[str, PoliciesItem]): + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Policies._item_type = PoliciesItem + + _fields: ClassVar[dict] = {"policies": {"type": Policies}, "_custom_data": {"type": dict}} + policies: Policies + """ + List of Internet-exit policies using this interface as exit. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, policies: Policies | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + CvPathfinderInternetExit. + + + Subclass of AvdModel. + + Args: + policies: + List of Internet-exit policies using this interface as exit. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "profile": {"type": str}, + "name": {"type": str}, + "description": {"type": str}, + "ip_address": {"type": str}, + "dhcp_ip": {"type": str}, + "public_ip": {"type": str}, + "encapsulation_dot1q_vlan": {"type": int}, + "dhcp_accept_default_route": {"type": bool, "default": True}, + "enabled": {"type": bool, "default": True}, + "speed": {"type": str}, + "peer": {"type": str}, + "peer_interface": {"type": str}, + "peer_ip": {"type": str}, + "bgp": {"type": Bgp}, + "ipv4_acl_in": {"type": str}, + "ipv4_acl_out": {"type": str}, + "static_routes": {"type": StaticRoutes}, + "qos_profile": {"type": str}, + "wan_carrier": {"type": str}, + "wan_circuit_id": {"type": str}, + "connected_to_pathfinder": {"type": bool, "default": True}, + "cv_pathfinder_internet_exit": {"type": CvPathfinderInternetExit}, + "raw_eos_cli": {"type": str}, + "flow_tracking": {"type": FlowTracking}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + profile: str + """ + L3 interface profile name. Any variable supported under `l3_interfaces` can be inherited from a + profile. + """ + name: str | None + """ + Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. + For a + subinterface, the parent physical interface is automatically created. + """ + description: str | None + """ + Interface description. + If not set a default description will be configured with '[[ + ]]'. + """ + ip_address: str | None + """Node IPv4 address/Mask or 'dhcp'.""" + dhcp_ip: str | None + """ + When the `ip_address` is `dhcp`, this optional field allows to indicate the expected + IPv4 address + (without mask) to be allocated on the interface if known. + This is not rendered in the configuration + but can be used for substitution of 'interface_ip' in the Access-list + set under `ipv4_acl_in` and + `ipv4_acl_out`. + """ + public_ip: str | None + """ + Node IPv4 address (no mask). + + This is used to get the public IP (if known) when the device is behind + NAT. + This is only used for `wan_rr` routers (AutoVPN RRs and Pathfinders) to determine the Public IP + with the following preference: + `wan_route_servers.path_groups.interfaces.ip_address` + -> + `l3_interfaces.public_ip` + -> `l3_interfaces.ip_address` + + The determined Public IP is used + by WAN routers when peering with this interface. + """ + encapsulation_dot1q_vlan: int | None + """ + For subinterfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + """ + dhcp_accept_default_route: bool + """ + Accept a default route from DHCP if `ip_address` is set to `dhcp`. + + Default value: `True` + """ + enabled: bool + """ + Enable or Shutdown the interface. + + Default value: `True` + """ + speed: str | None + """ + Speed should be set in the format `` or `forced ` or `auto + `. + """ + peer: str | None + """The peer device name. Used for description and documentation.""" + peer_interface: str | None + """The peer device interface. Used for description and documentation.""" + peer_ip: str | None + """ + The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true + and `ip` is an IP address. + """ + bgp: Bgp + """ + Enforce IPv4 BGP peering for the peer + + Subclass of AvdModel. + """ + ipv4_acl_in: str | None + """ + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + Required + for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under + `wan_carriers`. + """ + ipv4_acl_out: str | None + """ + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + """ + static_routes: StaticRoutes + """ + Configure IPv4 static routes pointing to `peer_ip`. + + Subclass of AvdList with `StaticRoutesItem` + items. + """ + qos_profile: str | None + """QOS service profile.""" + wan_carrier: str | None + """ + The WAN carrier this interface is connected to. + This is used to infer the path-groups in which this + interface should be configured. + Unless the carrier is marked as 'trusted' under `wan_carriers`, + `ipv4_acl_in` is also required on all WAN interfaces. + """ + wan_circuit_id: str | None + """ + The WAN circuit ID for this interface. + This is not rendered in the configuration but used for WAN + designs. + """ + connected_to_pathfinder: bool + """ + For a WAN interface (`wan_carrier` is set), allow to disable the static tunnel towards Pathfinders. + + Default value: `True` + """ + cv_pathfinder_internet_exit: CvPathfinderInternetExit + """ + PREVIEW: This key is in preview mode + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the interface in the final EOS configuration.""" + flow_tracking: FlowTracking + """ + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + """ + structured_config: StructuredConfig + """ + Custom structured config for the Ethernet interface. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + dhcp_ip: str | None | UndefinedType = Undefined, + public_ip: str | None | UndefinedType = Undefined, + encapsulation_dot1q_vlan: int | None | UndefinedType = Undefined, + dhcp_accept_default_route: bool | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + speed: str | None | UndefinedType = Undefined, + peer: str | None | UndefinedType = Undefined, + peer_interface: str | None | UndefinedType = Undefined, + peer_ip: str | None | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + ipv4_acl_in: str | None | UndefinedType = Undefined, + ipv4_acl_out: str | None | UndefinedType = Undefined, + static_routes: StaticRoutes | UndefinedType = Undefined, + qos_profile: str | None | UndefinedType = Undefined, + wan_carrier: str | None | UndefinedType = Undefined, + wan_circuit_id: str | None | UndefinedType = Undefined, + connected_to_pathfinder: bool | UndefinedType = Undefined, + cv_pathfinder_internet_exit: CvPathfinderInternetExit | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L3InterfaceProfilesItem. + + + Subclass of AvdModel. + + Args: + profile: + L3 interface profile name. Any variable supported under `l3_interfaces` can be inherited from a + profile. + name: + Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. + For a + subinterface, the parent physical interface is automatically created. + description: + Interface description. + If not set a default description will be configured with '[[ + ]]'. + ip_address: Node IPv4 address/Mask or 'dhcp'. + dhcp_ip: + When the `ip_address` is `dhcp`, this optional field allows to indicate the expected + IPv4 address + (without mask) to be allocated on the interface if known. + This is not rendered in the configuration + but can be used for substitution of 'interface_ip' in the Access-list + set under `ipv4_acl_in` and + `ipv4_acl_out`. + public_ip: + Node IPv4 address (no mask). + + This is used to get the public IP (if known) when the device is behind + NAT. + This is only used for `wan_rr` routers (AutoVPN RRs and Pathfinders) to determine the Public IP + with the following preference: + `wan_route_servers.path_groups.interfaces.ip_address` + -> + `l3_interfaces.public_ip` + -> `l3_interfaces.ip_address` + + The determined Public IP is used + by WAN routers when peering with this interface. + encapsulation_dot1q_vlan: + For subinterfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + dhcp_accept_default_route: Accept a default route from DHCP if `ip_address` is set to `dhcp`. + enabled: Enable or Shutdown the interface. + speed: + Speed should be set in the format `` or `forced ` or `auto + `. + peer: The peer device name. Used for description and documentation. + peer_interface: The peer device interface. Used for description and documentation. + peer_ip: + The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true + and `ip` is an IP address. + bgp: + Enforce IPv4 BGP peering for the peer + + Subclass of AvdModel. + ipv4_acl_in: + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + Required + for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under + `wan_carriers`. + ipv4_acl_out: + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + static_routes: + Configure IPv4 static routes pointing to `peer_ip`. + + Subclass of AvdList with `StaticRoutesItem` + items. + qos_profile: QOS service profile. + wan_carrier: + The WAN carrier this interface is connected to. + This is used to infer the path-groups in which this + interface should be configured. + Unless the carrier is marked as 'trusted' under `wan_carriers`, + `ipv4_acl_in` is also required on all WAN interfaces. + wan_circuit_id: + The WAN circuit ID for this interface. + This is not rendered in the configuration but used for WAN + designs. + connected_to_pathfinder: For a WAN interface (`wan_carrier` is set), allow to disable the static tunnel towards Pathfinders. + cv_pathfinder_internet_exit: + PREVIEW: This key is in preview mode + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the interface in the final EOS configuration. + flow_tracking: + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + structured_config: + Custom structured config for the Ethernet interface. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L3InterfaceProfiles(AvdIndexedList[str, L3InterfaceProfilesItem]): + """Subclass of AvdIndexedList with `L3InterfaceProfilesItem` items. Primary key is `profile` (`str`).""" + + _primary_key: ClassVar[str] = "profile" + + L3InterfaceProfiles._item_type = L3InterfaceProfilesItem + + class LocalUsers(EosCliConfigGen.LocalUsers): + pass + + class MacAddressTable(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"aging_time": {"type": int}, "_custom_data": {"type": dict}} + aging_time: int | None + """ + Aging time in seconds 10-1000000. + Enter 0 to disable aging. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, aging_time: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + MacAddressTable. + + + Subclass of AvdModel. + + Args: + aging_time: + Aging time in seconds 10-1000000. + Enter 0 to disable aging. + _custom_data: _custom_data + + """ + + class ManagementEapi(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enable_http": {"type": bool, "default": False}, + "enable_https": {"type": bool, "default": True}, + "default_services": {"type": bool}, + "_custom_data": {"type": dict}, + } + enable_http: bool + """Default value: `False`""" + enable_https: bool + """Default value: `True`""" + default_services: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enable_http: bool | UndefinedType = Undefined, + enable_https: bool | UndefinedType = Undefined, + default_services: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ManagementEapi. + + + Subclass of AvdModel. + + Args: + enable_http: enable_http + enable_https: enable_https + default_services: default_services + _custom_data: _custom_data + + """ + + class MgmtDestinationNetworks(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MgmtDestinationNetworks._item_type = str + + class MlagIbgpPeeringVrfs(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"base_vlan": {"type": int, "default": 3000}, "_custom_data": {"type": dict}} + base_vlan: int + """Default value: `3000`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, base_vlan: int | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + MlagIbgpPeeringVrfs. + + + Subclass of AvdModel. + + Args: + base_vlan: base_vlan + _custom_data: _custom_data + + """ + + class NameServers(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + NameServers._item_type = str + + class NetworkPortsItem(AvdModel): + """Subclass of AvdModel.""" + + class Switches(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Switches._item_type = str + + class SwitchPorts(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + SwitchPorts._item_type = str + + class TrunkGroups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + TrunkGroups._item_type = str + + class Flowcontrol(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"received": {"type": str}, "_custom_data": {"type": dict}} + received: Literal["received", "send", "on"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + received: Literal["received", "send", "on"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Flowcontrol. + + + Subclass of AvdModel. + + Args: + received: received + _custom_data: _custom_data + + """ + + class Ptp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "endpoint_role": {"type": str, "default": "follower"}, + "profile": {"type": str, "default": "aes67-r16-2016"}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + endpoint_role: Literal["bmca", "default", "follower"] + """Default value: `"follower"`""" + profile: str + """ + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + + Default value: `"aes67-r16-2016"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + endpoint_role: Literal["bmca", "default", "follower"] | UndefinedType = Undefined, + profile: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ptp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + endpoint_role: endpoint_role + profile: + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + _custom_data: _custom_data + + """ + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class LinkTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """ + Tracking group name. + The default group name is taken from fabric variable of the switch, + `link_tracking.groups[0].name` with default value being "LT_GROUP1". + Optional if default + link_tracking settings are configured on the node. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: + Tracking group name. + The default group name is taken from fabric variable of the switch, + `link_tracking.groups[0].name` with default value being "LT_GROUP1". + Optional if default + link_tracking settings are configured on the node. + _custom_data: _custom_data + + """ + + class Dot1x(EosCliConfigGen.EthernetInterfacesItem.Dot1x): + """Subclass of AvdModel.""" + + class Poe(EosCliConfigGen.EthernetInterfacesItem.Poe): + """Subclass of AvdModel.""" + + class StormControl(AvdModel): + """Subclass of AvdModel.""" + + class All(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional variable and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + All. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional variable and is hardware dependent. + _custom_data: _custom_data + + """ + + class Broadcast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional variable and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Broadcast. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional variable and is hardware dependent. + _custom_data: _custom_data + + """ + + class Multicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional variable and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Multicast. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional variable and is hardware dependent. + _custom_data: _custom_data + + """ + + class UnknownUnicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional variable and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + UnknownUnicast. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional variable and is hardware dependent. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "all": {"type": All}, + "broadcast": {"type": Broadcast}, + "multicast": {"type": Multicast}, + "unknown_unicast": {"type": UnknownUnicast}, + "_custom_data": {"type": dict}, + } + all: All + """Subclass of AvdModel.""" + broadcast: Broadcast + """Subclass of AvdModel.""" + multicast: Multicast + """Subclass of AvdModel.""" + unknown_unicast: UnknownUnicast + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + all: All | UndefinedType = Undefined, + broadcast: Broadcast | UndefinedType = Undefined, + multicast: Multicast | UndefinedType = Undefined, + unknown_unicast: UnknownUnicast | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StormControl. + + + Subclass of AvdModel. + + Args: + all: Subclass of AvdModel. + broadcast: Subclass of AvdModel. + multicast: Subclass of AvdModel. + unknown_unicast: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MonitorSessionsItem(AvdModel): + """Subclass of AvdModel.""" + + class SourceSettings(AvdModel): + """Subclass of AvdModel.""" + + class AccessGroup(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"type": {"type": str}, "name": {"type": str}, "priority": {"type": int}, "_custom_data": {"type": dict}} + type: Literal["ip", "ipv6", "mac"] | None + name: str | None + """ACL name.""" + priority: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + type: Literal["ip", "ipv6", "mac"] | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AccessGroup. + + + Subclass of AvdModel. + + Args: + type: type + name: ACL name. + priority: priority + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"direction": {"type": str}, "access_group": {"type": AccessGroup}, "_custom_data": {"type": dict}} + direction: Literal["rx", "tx", "both"] | None + access_group: AccessGroup + """ + This can only be set when `session_settings.access_group` is not set. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction: Literal["rx", "tx", "both"] | None | UndefinedType = Undefined, + access_group: AccessGroup | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SourceSettings. + + + Subclass of AvdModel. + + Args: + direction: direction + access_group: + This can only be set when `session_settings.access_group` is not set. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class SessionSettings(AvdModel): + """Subclass of AvdModel.""" + + class AccessGroup(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"type": {"type": str}, "name": {"type": str}, "_custom_data": {"type": dict}} + type: Literal["ip", "ipv6", "mac"] | None + name: str | None + """ACL name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + type: Literal["ip", "ipv6", "mac"] | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AccessGroup. + + + Subclass of AvdModel. + + Args: + type: type + name: ACL name. + _custom_data: _custom_data + + """ + + class Truncate(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "size": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool | None + size: int | None + """Size in bytes.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + size: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Truncate. + + + Subclass of AvdModel. + + Args: + enabled: enabled + size: Size in bytes. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "encapsulation_gre_metadata_tx": {"type": bool}, + "header_remove_size": {"type": int}, + "access_group": {"type": AccessGroup}, + "rate_limit_per_ingress_chip": {"type": str}, + "rate_limit_per_egress_chip": {"type": str}, + "sample": {"type": int}, + "truncate": {"type": Truncate}, + "_custom_data": {"type": dict}, + } + encapsulation_gre_metadata_tx: bool | None + header_remove_size: int | None + """Number of bytes to remove from header.""" + access_group: AccessGroup + """Subclass of AvdModel.""" + rate_limit_per_ingress_chip: str | None + """ + Ratelimit and unit as string. + Examples: + "100000 bps" + "100 kbps" + "10 mbps" + """ + rate_limit_per_egress_chip: str | None + """ + Ratelimit and unit as string. + Examples: + "100000 bps" + "100 kbps" + "10 mbps" + """ + sample: int | None + truncate: Truncate + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + encapsulation_gre_metadata_tx: bool | None | UndefinedType = Undefined, + header_remove_size: int | None | UndefinedType = Undefined, + access_group: AccessGroup | UndefinedType = Undefined, + rate_limit_per_ingress_chip: str | None | UndefinedType = Undefined, + rate_limit_per_egress_chip: str | None | UndefinedType = Undefined, + sample: int | None | UndefinedType = Undefined, + truncate: Truncate | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SessionSettings. + + + Subclass of AvdModel. + + Args: + encapsulation_gre_metadata_tx: encapsulation_gre_metadata_tx + header_remove_size: Number of bytes to remove from header. + access_group: Subclass of AvdModel. + rate_limit_per_ingress_chip: + Ratelimit and unit as string. + Examples: # fmt: skip + "100000 bps" + "100 kbps" + "10 mbps" + rate_limit_per_egress_chip: + Ratelimit and unit as string. + Examples: # fmt: skip + "100000 bps" + "100 kbps" + "10 mbps" + sample: sample + truncate: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "role": {"type": str}, + "source_settings": {"type": SourceSettings}, + "session_settings": {"type": SessionSettings}, + "_custom_data": {"type": dict}, + } + name: str + """Session name.""" + role: Literal["source", "destination"] | None + source_settings: SourceSettings + """Subclass of AvdModel.""" + session_settings: SessionSettings + """ + Session settings are defined per session name. + Different session_settings for the same session name + will be combined/merged. + + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + role: Literal["source", "destination"] | None | UndefinedType = Undefined, + source_settings: SourceSettings | UndefinedType = Undefined, + session_settings: SessionSettings | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MonitorSessionsItem. + + + Subclass of AvdModel. + + Args: + name: Session name. + role: role + source_settings: Subclass of AvdModel. + session_settings: + Session settings are defined per session name. + Different session_settings for the same session name + will be combined/merged. + + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MonitorSessions(AvdList[MonitorSessionsItem]): + """Subclass of AvdList with `MonitorSessionsItem` items.""" + + MonitorSessions._item_type = MonitorSessionsItem + + class EthernetSegment(AvdModel): + """Subclass of AvdModel.""" + + class DesignatedForwarderPreferences(AvdList[int]): + """Subclass of AvdList with `int` items.""" + + DesignatedForwarderPreferences._item_type = int + + _fields: ClassVar[dict] = { + "short_esi": {"type": str}, + "redundancy": {"type": str}, + "designated_forwarder_algorithm": {"type": str}, + "designated_forwarder_preferences": {"type": DesignatedForwarderPreferences}, + "dont_preempt": {"type": bool}, + "_custom_data": {"type": dict}, + } + short_esi: str + """ + In format xxxx:xxxx:xxxx or "auto". + Define a manual short-esi (be careful using this on profiles) or + set the value to "auto" to automatically generate the value. + Please see the notes under "EVPN A/A + ESI dual and single-attached endpoint scenarios" before setting `short_esi: auto`. + """ + redundancy: Literal["all-active", "single-active"] | None + """ + If omitted, Port-Channels use the EOS default of all-active. + If omitted, Ethernet interfaces are + configured as single-active. + """ + designated_forwarder_algorithm: Literal["auto", "modulus", "preference"] | None + """ + Configure DF algorithm and preferences. + - auto: Use preference-based algorithm and assign preference + based on position of device in the 'switches' list, + e.g., assuming a list of three switches, this + would assign a preference of 200 to the first switch, 100 to the 2nd, and 0 to the third. + - + preference: Set preference for each switch manually using designated_forwarder_preferences key. + - + modulus: Use the default modulus-based algorithm. + If omitted, Port-Channels use the EOS default of + modulus. + If omitted, Ethernet interfaces default to the 'auto' mechanism detailed above. + """ + designated_forwarder_preferences: DesignatedForwarderPreferences + """ + Manual preference as described above, required only for preference algorithm. + + Subclass of AvdList + with `int` items. + """ + dont_preempt: bool | None + """Disable preemption for single-active forwarding when auto/manual DF preference is configured.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + short_esi: str | UndefinedType = Undefined, + redundancy: Literal["all-active", "single-active"] | None | UndefinedType = Undefined, + designated_forwarder_algorithm: Literal["auto", "modulus", "preference"] | None | UndefinedType = Undefined, + designated_forwarder_preferences: DesignatedForwarderPreferences | UndefinedType = Undefined, + dont_preempt: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EthernetSegment. + + + Subclass of AvdModel. + + Args: + short_esi: + In format xxxx:xxxx:xxxx or "auto". + Define a manual short-esi (be careful using this on profiles) or + set the value to "auto" to automatically generate the value. + Please see the notes under "EVPN A/A + ESI dual and single-attached endpoint scenarios" before setting `short_esi: auto`. + redundancy: + If omitted, Port-Channels use the EOS default of all-active. + If omitted, Ethernet interfaces are + configured as single-active. + designated_forwarder_algorithm: + Configure DF algorithm and preferences. + - auto: Use preference-based algorithm and assign preference + based on position of device in the 'switches' list, + e.g., assuming a list of three switches, this + would assign a preference of 200 to the first switch, 100 to the 2nd, and 0 to the third. + - + preference: Set preference for each switch manually using designated_forwarder_preferences key. + - + modulus: Use the default modulus-based algorithm. + If omitted, Port-Channels use the EOS default of + modulus. + If omitted, Ethernet interfaces default to the 'auto' mechanism detailed above. + designated_forwarder_preferences: + Manual preference as described above, required only for preference algorithm. + + Subclass of AvdList + with `int` items. + dont_preempt: Disable preemption for single-active forwarding when auto/manual DF preference is configured. + _custom_data: _custom_data + + """ + + class PortChannel(AvdModel): + """Subclass of AvdModel.""" + + class LacpFallback(AvdModel): + """Subclass of AvdModel.""" + + class Individual(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "_custom_data": {"type": dict}} + profile: str | None + """Port-profile name to inherit configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, profile: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Individual. + + + Subclass of AvdModel. + + Args: + profile: Port-profile name to inherit configuration. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"mode": {"type": str}, "individual": {"type": Individual}, "timeout": {"type": int}, "_custom_data": {"type": dict}} + mode: Literal["static", "individual"] | None + """ + Either static or individual mode is supported. + If the mode is set to "individual" the + "individual.profile" setting must be defined. + """ + individual: Individual + """ + Define parameters for port-channel member interfaces. Applies only if LACP fallback is set to + "individual". + + Subclass of AvdModel. + """ + timeout: int | None + """Timeout in seconds. EOS default is 90 seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["static", "individual"] | None | UndefinedType = Undefined, + individual: Individual | UndefinedType = Undefined, + timeout: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LacpFallback. + + + Subclass of AvdModel. + + Args: + mode: + Either static or individual mode is supported. + If the mode is set to "individual" the + "individual.profile" setting must be defined. + individual: + Define parameters for port-channel member interfaces. Applies only if LACP fallback is set to + "individual". + + Subclass of AvdModel. + timeout: Timeout in seconds. EOS default is 90 seconds. + _custom_data: _custom_data + + """ + + class LacpTimer(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"mode": {"type": str}, "multiplier": {"type": int}, "_custom_data": {"type": dict}} + mode: Literal["normal", "fast"] | None + """LACP mode for interface members.""" + multiplier: int | None + """Number of LACP BPDUs lost before deeming the peer down. EOS default is 3.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["normal", "fast"] | None | UndefinedType = Undefined, + multiplier: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LacpTimer. + + + Subclass of AvdModel. + + Args: + mode: LACP mode for interface members. + multiplier: Number of LACP BPDUs lost before deeming the peer down. EOS default is 3. + _custom_data: _custom_data + + """ + + class SubinterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class EncapsulationVlan(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"client_dot1q": {"type": int}, "_custom_data": {"type": dict}} + client_dot1q: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, client_dot1q: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + EncapsulationVlan. + + + Subclass of AvdModel. + + Args: + client_dot1q: client_dot1q + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "number": {"type": int}, + "short_esi": {"type": str}, + "vlan_id": {"type": int}, + "encapsulation_vlan": {"type": EncapsulationVlan}, + "_custom_data": {"type": dict}, + } + number: int | None + """Subinterface number.""" + short_esi: str | None + """ + In format xxxx:xxxx:xxxx or "auto". + Required for multihomed port-channels with subinterfaces. + """ + vlan_id: int | None + """ + VLAN ID to bridge. + Default is subinterface number. + """ + encapsulation_vlan: EncapsulationVlan + """ + Client VLAN ID encapsulation. + Default is subinterface number. + + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + number: int | None | UndefinedType = Undefined, + short_esi: str | None | UndefinedType = Undefined, + vlan_id: int | None | UndefinedType = Undefined, + encapsulation_vlan: EncapsulationVlan | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SubinterfacesItem. + + + Subclass of AvdModel. + + Args: + number: Subinterface number. + short_esi: + In format xxxx:xxxx:xxxx or "auto". + Required for multihomed port-channels with subinterfaces. + vlan_id: + VLAN ID to bridge. + Default is subinterface number. + encapsulation_vlan: + Client VLAN ID encapsulation. + Default is subinterface number. + + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Subinterfaces(AvdList[SubinterfacesItem]): + """Subclass of AvdList with `SubinterfacesItem` items.""" + + Subinterfaces._item_type = SubinterfacesItem + + class StructuredConfig(EosCliConfigGen.PortChannelInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "mode": {"type": str}, + "channel_id": {"type": int}, + "description": {"type": str}, + "endpoint_port_channel": {"type": str}, + "enabled": {"type": bool, "default": True}, + "ptp_mpass": {"type": bool, "default": False}, + "lacp_fallback": {"type": LacpFallback}, + "lacp_timer": {"type": LacpTimer}, + "subinterfaces": {"type": Subinterfaces}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + mode: Literal["active", "passive", "on"] | None + """Port-Channel Mode.""" + channel_id: int | None + """ + Port-Channel ID. + If no channel_id is specified, an id is generated from the first switch port in the + port channel. + """ + description: str | None + """ + Description or description template to be used on the port-channel interface. + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `endpoint_type` - the `type` from `connected_endpoints_keys` like `server`, `router` etc. + - + `endpoint` - The name of the connected endpoint + - `endpoint_port_channel` - The value from + `endpoint_port_channel` if set. + - `port_channel_id` - The port-channel number for the switch. + - + `adapter_description` - The adapter's description if set. + - `adapter_description_or_endpoint` - + Helper alias of the adapter_description or endpoint. + + The default description is set by + `default_connected_endpoints_port_channel_description`. + By default the description is templated from + the type, name and port_channel interface of the endpoint if set. + """ + endpoint_port_channel: str | None + """ + Name of the port-channel interface on the endpoint. + Used for the port-channel description template + with the field name `peer_interface` + """ + enabled: bool + """ + Port-Channel administrative state. + Setting to false will set port to 'shutdown' in intended + configuration. + + Default value: `True` + """ + ptp_mpass: bool + """ + When MPASS is enabled on an MLAG port-channel, MLAG peers coordinate to function as a single PTP + logical device. + Arista PTP enabled devices always place PTP messages on the same physical link + within the port-channel. + Hence, MPASS is needed only on MLAG port-channels connected to non-Arista + devices. + + Default value: `False` + """ + lacp_fallback: LacpFallback + """ + LACP fallback configuration. + + Subclass of AvdModel. + """ + lacp_timer: LacpTimer + """ + LACP timer configuration. Applies only when Port-channel mode is not "on". + + Subclass of AvdModel. + """ + subinterfaces: Subinterfaces + """ + Port-Channel L2 Subinterfaces + Subinterfaces are only supported on routed port-channels, which means + they cannot be configured on MLAG port-channels. + Setting short_esi: auto generates the short_esi + automatically using a hash of configuration elements. + Please see the notes under "EVPN A/A ESI dual- + attached endpoint scenario" before setting short_esi: auto. + + + Subclass of AvdList with + `SubinterfacesItem` items. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the port-channel interface in the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["active", "passive", "on"] | None | UndefinedType = Undefined, + channel_id: int | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + endpoint_port_channel: str | None | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + ptp_mpass: bool | UndefinedType = Undefined, + lacp_fallback: LacpFallback | UndefinedType = Undefined, + lacp_timer: LacpTimer | UndefinedType = Undefined, + subinterfaces: Subinterfaces | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PortChannel. + + + Subclass of AvdModel. + + Args: + mode: Port-Channel Mode. + channel_id: + Port-Channel ID. + If no channel_id is specified, an id is generated from the first switch port in the + port channel. + description: + Description or description template to be used on the port-channel interface. + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `endpoint_type` - the `type` from `connected_endpoints_keys` like `server`, `router` etc. + - + `endpoint` - The name of the connected endpoint + - `endpoint_port_channel` - The value from + `endpoint_port_channel` if set. + - `port_channel_id` - The port-channel number for the switch. + - + `adapter_description` - The adapter's description if set. + - `adapter_description_or_endpoint` - + Helper alias of the adapter_description or endpoint. + + The default description is set by + `default_connected_endpoints_port_channel_description`. + By default the description is templated from + the type, name and port_channel interface of the endpoint if set. + endpoint_port_channel: + Name of the port-channel interface on the endpoint. + Used for the port-channel description template + with the field name `peer_interface` + enabled: + Port-Channel administrative state. + Setting to false will set port to 'shutdown' in intended + configuration. + ptp_mpass: + When MPASS is enabled on an MLAG port-channel, MLAG peers coordinate to function as a single PTP + logical device. + Arista PTP enabled devices always place PTP messages on the same physical link + within the port-channel. + Hence, MPASS is needed only on MLAG port-channels connected to non-Arista + devices. + lacp_fallback: + LACP fallback configuration. + + Subclass of AvdModel. + lacp_timer: + LACP timer configuration. Applies only when Port-channel mode is not "on". + + Subclass of AvdModel. + subinterfaces: + Port-Channel L2 Subinterfaces + Subinterfaces are only supported on routed port-channels, which means + they cannot be configured on MLAG port-channels. + Setting short_esi: auto generates the short_esi + automatically using a hash of configuration elements. + Please see the notes under "EVPN A/A ESI dual- + attached endpoint scenario" before setting short_esi: auto. + + + Subclass of AvdList with + `SubinterfacesItem` items. + raw_eos_cli: EOS CLI rendered directly on the port-channel interface in the final EOS configuration. + structured_config: + Custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "switches": {"type": Switches}, + "switch_ports": {"type": SwitchPorts}, + "description": {"type": str}, + "endpoint": {"type": str}, + "speed": {"type": str}, + "profile": {"type": str}, + "enabled": {"type": bool, "default": True}, + "mode": {"type": str}, + "mtu": {"type": int}, + "l2_mtu": {"type": int}, + "l2_mru": {"type": int}, + "native_vlan": {"type": int}, + "native_vlan_tag": {"type": bool}, + "phone_vlan": {"type": int}, + "phone_trunk_mode": {"type": str}, + "trunk_groups": {"type": TrunkGroups}, + "vlans": {"type": str}, + "spanning_tree_portfast": {"type": str}, + "spanning_tree_bpdufilter": {"type": str}, + "spanning_tree_bpduguard": {"type": str}, + "flowcontrol": {"type": Flowcontrol}, + "qos_profile": {"type": str}, + "ptp": {"type": Ptp}, + "sflow": {"type": bool}, + "flow_tracking": {"type": FlowTracking}, + "link_tracking": {"type": LinkTracking}, + "dot1x": {"type": Dot1x}, + "poe": {"type": Poe}, + "storm_control": {"type": StormControl}, + "monitor_sessions": {"type": MonitorSessions}, + "ethernet_segment": {"type": EthernetSegment}, + "port_channel": {"type": PortChannel}, + "validate_state": {"type": bool}, + "validate_lldp": {"type": bool}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + switches: Switches + """ + Regex matching the full hostname of one or more switches. + The regular expression must match the full + hostname. + + + Subclass of AvdList with `str` items. + """ + switch_ports: SwitchPorts + """ + List of ranges using AVD range_expand syntax. + For example: + + switch_ports: + - Ethernet1 + - + Ethernet2-48 + + All switch_ports ranges are expanded into individual port configurations. + + For more + details and examples of the `range_expand` syntax, see the [`arista.avd.range_expand` + documentation](../../../docs/plugins/Filter_plugins/range_expand.md). + + + Subclass of AvdList with + `str` items. + """ + description: str | None + """ + Description or description template to be used on all ports. + This can be a template using the AVD + string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom- + descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - + `endpoint_type` - always set to `network_port`. + - `endpoint` - content of the `endpoint` key if + set. + - `port_channel_id`: The port-channel number for the switch. + + The default description is set + by `default_network_ports_description`. + By default the description is templated from the `endpoint` + key if set. + """ + endpoint: str | None + """Name or description of the endpoints connected to these ports.""" + speed: str | None + """ + Set adapter speed in the format `` or `forced ` or `auto + `. + If not specified speed will be auto. + """ + profile: str | None + """Port-profile name to inherit configuration.""" + enabled: bool + """ + Administrative state, setting to false will set the port to 'shutdown' in the intended + configuration. + + Default value: `True` + """ + mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None + """Interface mode.""" + mtu: int | None + l2_mtu: int | None + """"l2_mtu" should only be defined for platforms supporting the "l2 mtu" CLI.""" + l2_mru: int | None + """"l2_mru" should only be defined for platforms supporting the "l2 mru" CLI.""" + native_vlan: int | None + """ + Native VLAN for a trunk port. + If both `native_vlan` and `native_vlan_tag` are set, `native_vlan_tag` + takes precedence. + """ + native_vlan_tag: bool | None + """If both `native_vlan` and `native_vlan_tag` are set, `native_vlan_tag` takes precedence.""" + phone_vlan: int | None + """ + Phone VLAN for a mode `trunk phone` port. + Requires `mode: trunk phone` to be set. + """ + phone_trunk_mode: Literal["tagged", "untagged", "tagged phone", "untagged phone"] | None + """ + Specify if the phone traffic is tagged or untagged. + If both data and phone traffic are untagged, + MAC-Based VLAN Assignment (MBVA) is used, if supported by the model of switch. + """ + trunk_groups: TrunkGroups + """ + Required with `enable_trunk_groups: true`. + Trunk Groups are used for limiting VLANs on trunk ports + to VLANs with the same Trunk Group. + + + Subclass of AvdList with `str` items. + """ + vlans: str | None + """ + Interface VLANs - if not set, the EOS default is that all VLANs are allowed for trunk ports, and + VLAN 1 will be used for access ports. + """ + spanning_tree_portfast: Literal["edge", "network"] | None + spanning_tree_bpdufilter: Literal["enabled", "disabled", "True", "False", "true", "false"] | None + spanning_tree_bpduguard: Literal["enabled", "disabled", "True", "False", "true", "false"] | None + flowcontrol: Flowcontrol + """Subclass of AvdModel.""" + qos_profile: str | None + """QOS profile name.""" + ptp: Ptp + """ + The global PTP profile parameters will be applied to all connected endpoints where `ptp` is manually + enabled. + `ptp role master` is set to ensure control over the PTP topology. + + + Subclass of AvdModel. + """ + sflow: bool | None + """Configures sFlow on the interface. Overrides `fabric_sflow.endpoints` setting.""" + flow_tracking: FlowTracking + """ + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.endpoints` setting. + Subclass of AvdModel. + """ + link_tracking: LinkTracking + """ + Configure the downstream interfaces of a respective Link Tracking Group. + If `port_channel` is + defined in an adapter, then the port-channel interface is configured to be the downstream. + Else all + the ethernet interfaces will be configured as downstream -> to configure single-active EVPN + multihomed networks. + + + Subclass of AvdModel. + """ + dot1x: Dot1x + """ + 802.1x + + Subclass of AvdModel. + """ + poe: Poe + """ + Power Over Ethernet settings applied on port. Only configured if platform supports PoE. + + Subclass of + AvdModel. + """ + storm_control: StormControl + """ + Storm control settings applied on port toward the endpoint. + + Subclass of AvdModel. + """ + monitor_sessions: MonitorSessions + """ + Used to define switchports as source or destination for monitoring sessions. + + Subclass of AvdList + with `MonitorSessionsItem` items. + """ + ethernet_segment: EthernetSegment + """ + Settings for all or single-active EVPN multihoming. + + Subclass of AvdModel. + """ + port_channel: PortChannel + """ + Used for port-channel adapter. + + Subclass of AvdModel. + """ + validate_state: bool | None + """ + Set to false to disable interface state and LLDP topology validation performed by the + `eos_validate_state` role. + """ + validate_lldp: bool | None + """Set to false to disable the LLDP topology validation performed by the `eos_validate_state` role.""" + raw_eos_cli: str | None + """EOS CLI rendered directly on the ethernet interface in the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config added under ethernet_interfaces.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + switches: Switches | UndefinedType = Undefined, + switch_ports: SwitchPorts | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + endpoint: str | None | UndefinedType = Undefined, + speed: str | None | UndefinedType = Undefined, + profile: str | None | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + l2_mtu: int | None | UndefinedType = Undefined, + l2_mru: int | None | UndefinedType = Undefined, + native_vlan: int | None | UndefinedType = Undefined, + native_vlan_tag: bool | None | UndefinedType = Undefined, + phone_vlan: int | None | UndefinedType = Undefined, + phone_trunk_mode: Literal["tagged", "untagged", "tagged phone", "untagged phone"] | None | UndefinedType = Undefined, + trunk_groups: TrunkGroups | UndefinedType = Undefined, + vlans: str | None | UndefinedType = Undefined, + spanning_tree_portfast: Literal["edge", "network"] | None | UndefinedType = Undefined, + spanning_tree_bpdufilter: Literal["enabled", "disabled", "True", "False", "true", "false"] | None | UndefinedType = Undefined, + spanning_tree_bpduguard: Literal["enabled", "disabled", "True", "False", "true", "false"] | None | UndefinedType = Undefined, + flowcontrol: Flowcontrol | UndefinedType = Undefined, + qos_profile: str | None | UndefinedType = Undefined, + ptp: Ptp | UndefinedType = Undefined, + sflow: bool | None | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + link_tracking: LinkTracking | UndefinedType = Undefined, + dot1x: Dot1x | UndefinedType = Undefined, + poe: Poe | UndefinedType = Undefined, + storm_control: StormControl | UndefinedType = Undefined, + monitor_sessions: MonitorSessions | UndefinedType = Undefined, + ethernet_segment: EthernetSegment | UndefinedType = Undefined, + port_channel: PortChannel | UndefinedType = Undefined, + validate_state: bool | None | UndefinedType = Undefined, + validate_lldp: bool | None | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NetworkPortsItem. + + + Subclass of AvdModel. + + Args: + switches: + Regex matching the full hostname of one or more switches. + The regular expression must match the full + hostname. + + + Subclass of AvdList with `str` items. + switch_ports: + List of ranges using AVD range_expand syntax. + For example: + + switch_ports: + - Ethernet1 + - + Ethernet2-48 + + All switch_ports ranges are expanded into individual port configurations. + + For more + details and examples of the `range_expand` syntax, see the [`arista.avd.range_expand` + documentation](../../../docs/plugins/Filter_plugins/range_expand.md). + + + Subclass of AvdList with + `str` items. + description: + Description or description template to be used on all ports. + This can be a template using the AVD + string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom- + descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - + `endpoint_type` - always set to `network_port`. + - `endpoint` - content of the `endpoint` key if + set. + - `port_channel_id`: The port-channel number for the switch. + + The default description is set + by `default_network_ports_description`. + By default the description is templated from the `endpoint` + key if set. + endpoint: Name or description of the endpoints connected to these ports. + speed: + Set adapter speed in the format `` or `forced ` or `auto + `. + If not specified speed will be auto. + profile: Port-profile name to inherit configuration. + enabled: + Administrative state, setting to false will set the port to 'shutdown' in the intended + configuration. + mode: Interface mode. + mtu: mtu + l2_mtu: "l2_mtu" should only be defined for platforms supporting the "l2 mtu" CLI. + l2_mru: "l2_mru" should only be defined for platforms supporting the "l2 mru" CLI. + native_vlan: + Native VLAN for a trunk port. + If both `native_vlan` and `native_vlan_tag` are set, `native_vlan_tag` + takes precedence. + native_vlan_tag: If both `native_vlan` and `native_vlan_tag` are set, `native_vlan_tag` takes precedence. + phone_vlan: + Phone VLAN for a mode `trunk phone` port. + Requires `mode: trunk phone` to be set. + phone_trunk_mode: + Specify if the phone traffic is tagged or untagged. + If both data and phone traffic are untagged, + MAC-Based VLAN Assignment (MBVA) is used, if supported by the model of switch. + trunk_groups: + Required with `enable_trunk_groups: true`. + Trunk Groups are used for limiting VLANs on trunk ports + to VLANs with the same Trunk Group. + + + Subclass of AvdList with `str` items. + vlans: + Interface VLANs - if not set, the EOS default is that all VLANs are allowed for trunk ports, and + VLAN 1 will be used for access ports. + spanning_tree_portfast: spanning_tree_portfast + spanning_tree_bpdufilter: spanning_tree_bpdufilter + spanning_tree_bpduguard: spanning_tree_bpduguard + flowcontrol: Subclass of AvdModel. + qos_profile: QOS profile name. + ptp: + The global PTP profile parameters will be applied to all connected endpoints where `ptp` is manually + enabled. + `ptp role master` is set to ensure control over the PTP topology. + + + Subclass of AvdModel. + sflow: Configures sFlow on the interface. Overrides `fabric_sflow.endpoints` setting. + flow_tracking: + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.endpoints` setting. + Subclass of AvdModel. + link_tracking: + Configure the downstream interfaces of a respective Link Tracking Group. + If `port_channel` is + defined in an adapter, then the port-channel interface is configured to be the downstream. + Else all + the ethernet interfaces will be configured as downstream -> to configure single-active EVPN + multihomed networks. + + + Subclass of AvdModel. + dot1x: + 802.1x + + Subclass of AvdModel. + poe: + Power Over Ethernet settings applied on port. Only configured if platform supports PoE. + + Subclass of + AvdModel. + storm_control: + Storm control settings applied on port toward the endpoint. + + Subclass of AvdModel. + monitor_sessions: + Used to define switchports as source or destination for monitoring sessions. + + Subclass of AvdList + with `MonitorSessionsItem` items. + ethernet_segment: + Settings for all or single-active EVPN multihoming. + + Subclass of AvdModel. + port_channel: + Used for port-channel adapter. + + Subclass of AvdModel. + validate_state: + Set to false to disable interface state and LLDP topology validation performed by the + `eos_validate_state` role. + validate_lldp: Set to false to disable the LLDP topology validation performed by the `eos_validate_state` role. + raw_eos_cli: EOS CLI rendered directly on the ethernet interface in the final EOS configuration. + structured_config: + Custom structured config added under ethernet_interfaces.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class NetworkPorts(AvdList[NetworkPortsItem]): + """Subclass of AvdList with `NetworkPortsItem` items.""" + + NetworkPorts._item_type = NetworkPortsItem + + class NetworkServicesKeysItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "_custom_data": {"type": dict}} + name: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, name: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + NetworkServicesKeysItem. + + + Subclass of AvdModel. + + Args: + name: name + _custom_data: _custom_data + + """ + + class NetworkServicesKeys(AvdIndexedList[str, NetworkServicesKeysItem]): + """Subclass of AvdIndexedList with `NetworkServicesKeysItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + NetworkServicesKeys._item_type = NetworkServicesKeysItem + + class CustomNodeTypeKeysItem(AvdModel): + """Subclass of AvdModel.""" + + class DefaultOverlayAddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DefaultOverlayAddressFamilies._item_type = str + + class NetworkServices(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "l1": {"type": bool, "default": False}, + "l2": {"type": bool, "default": False}, + "l3": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + l1: bool + """ + ?? + + Default value: `False` + """ + l2: bool + """ + Vlans + + Default value: `False` + """ + l3: bool + """ + VRFs, SVIs (if l2 is true). + Only supported with underlay_router. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + l1: bool | UndefinedType = Undefined, + l2: bool | UndefinedType = Undefined, + l3: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NetworkServices. + + + Subclass of AvdModel. + + Args: + l1: ?? + l2: Vlans + l3: + VRFs, SVIs (if l2 is true). + Only supported with underlay_router. + _custom_data: _custom_data + + """ + + class IpAddressing(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "python_module": {"type": str}, + "python_class_name": {"type": str, "default": "AvdIpAddressing"}, + "router_id": {"type": str}, + "router_id_ipv6": {"type": str}, + "mlag_ip_primary": {"type": str}, + "mlag_ip_secondary": {"type": str}, + "mlag_l3_ip_primary": {"type": str}, + "mlag_l3_ip_secondary": {"type": str}, + "mlag_ibgp_peering_ip_primary": {"type": str}, + "mlag_ibgp_peering_ip_secondary": {"type": str}, + "p2p_uplinks_ip": {"type": str}, + "p2p_uplinks_peer_ip": {"type": str}, + "vtep_ip_mlag": {"type": str}, + "vtep_ip": {"type": str}, + "_custom_data": {"type": dict}, + } + python_module: str | None + """Custom Python Module to import for IP addressing.""" + python_class_name: str + """ + Name of Custom Python Class to import for IP addressing. + + Default value: `"AvdIpAddressing"` + """ + router_id: str | None + """Path to Custom J2 template.""" + router_id_ipv6: str | None + """Path to Custom J2 template.""" + mlag_ip_primary: str | None + """Path to Custom J2 template.""" + mlag_ip_secondary: str | None + """Path to Custom J2 template.""" + mlag_l3_ip_primary: str | None + """Path to Custom J2 template.""" + mlag_l3_ip_secondary: str | None + """Path to Custom J2 template.""" + mlag_ibgp_peering_ip_primary: str | None + """Path to Custom J2 template.""" + mlag_ibgp_peering_ip_secondary: str | None + """Path to Custom J2 template.""" + p2p_uplinks_ip: str | None + """Path to Custom J2 template.""" + p2p_uplinks_peer_ip: str | None + """Path to Custom J2 template.""" + vtep_ip_mlag: str | None + """Path to Custom J2 template.""" + vtep_ip: str | None + """Path to Custom J2 template.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + python_module: str | None | UndefinedType = Undefined, + python_class_name: str | UndefinedType = Undefined, + router_id: str | None | UndefinedType = Undefined, + router_id_ipv6: str | None | UndefinedType = Undefined, + mlag_ip_primary: str | None | UndefinedType = Undefined, + mlag_ip_secondary: str | None | UndefinedType = Undefined, + mlag_l3_ip_primary: str | None | UndefinedType = Undefined, + mlag_l3_ip_secondary: str | None | UndefinedType = Undefined, + mlag_ibgp_peering_ip_primary: str | None | UndefinedType = Undefined, + mlag_ibgp_peering_ip_secondary: str | None | UndefinedType = Undefined, + p2p_uplinks_ip: str | None | UndefinedType = Undefined, + p2p_uplinks_peer_ip: str | None | UndefinedType = Undefined, + vtep_ip_mlag: str | None | UndefinedType = Undefined, + vtep_ip: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpAddressing. + + + Subclass of AvdModel. + + Args: + python_module: Custom Python Module to import for IP addressing. + python_class_name: Name of Custom Python Class to import for IP addressing. + router_id: Path to Custom J2 template. + router_id_ipv6: Path to Custom J2 template. + mlag_ip_primary: Path to Custom J2 template. + mlag_ip_secondary: Path to Custom J2 template. + mlag_l3_ip_primary: Path to Custom J2 template. + mlag_l3_ip_secondary: Path to Custom J2 template. + mlag_ibgp_peering_ip_primary: Path to Custom J2 template. + mlag_ibgp_peering_ip_secondary: Path to Custom J2 template. + p2p_uplinks_ip: Path to Custom J2 template. + p2p_uplinks_peer_ip: Path to Custom J2 template. + vtep_ip_mlag: Path to Custom J2 template. + vtep_ip: Path to Custom J2 template. + _custom_data: _custom_data + + """ + + class InterfaceDescriptions(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "python_module": {"type": str}, + "python_class_name": {"type": str, "default": "AvdInterfaceDescriptions"}, + "underlay_ethernet_interfaces": {"type": str}, + "underlay_port_channel_interfaces": {"type": str}, + "mlag_ethernet_interfaces": {"type": str}, + "mlag_port_channel_interfaces": {"type": str}, + "connected_endpoints_ethernet_interfaces": {"type": str}, + "connected_endpoints_port_channel_interfaces": {"type": str}, + "router_id_loopback_interface": {"type": str}, + "vtep_loopback_interface": {"type": str}, + "overlay_loopback_interface": {"type": str}, + "_custom_data": {"type": dict}, + } + python_module: str | None + """Custom Python Module to import for interface descriptions.""" + python_class_name: str + """ + Name of Custom Python Class to import for interface descriptions. + + Default value: `"AvdInterfaceDescriptions"` + """ + underlay_ethernet_interfaces: str | None + """Path to Custom J2 template.""" + underlay_port_channel_interfaces: str | None + """Path to Custom J2 template.""" + mlag_ethernet_interfaces: str | None + """Path to Custom J2 template.""" + mlag_port_channel_interfaces: str | None + """Path to Custom J2 template.""" + connected_endpoints_ethernet_interfaces: str | None + """Path to Custom J2 template.""" + connected_endpoints_port_channel_interfaces: str | None + """Path to Custom J2 template.""" + router_id_loopback_interface: str | None + """Path to Custom J2 template.""" + vtep_loopback_interface: str | None + """Path to Custom J2 template.""" + overlay_loopback_interface: str | None + """Path to Custom J2 template.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + python_module: str | None | UndefinedType = Undefined, + python_class_name: str | UndefinedType = Undefined, + underlay_ethernet_interfaces: str | None | UndefinedType = Undefined, + underlay_port_channel_interfaces: str | None | UndefinedType = Undefined, + mlag_ethernet_interfaces: str | None | UndefinedType = Undefined, + mlag_port_channel_interfaces: str | None | UndefinedType = Undefined, + connected_endpoints_ethernet_interfaces: str | None | UndefinedType = Undefined, + connected_endpoints_port_channel_interfaces: str | None | UndefinedType = Undefined, + router_id_loopback_interface: str | None | UndefinedType = Undefined, + vtep_loopback_interface: str | None | UndefinedType = Undefined, + overlay_loopback_interface: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + InterfaceDescriptions. + + + Subclass of AvdModel. + + Args: + python_module: Custom Python Module to import for interface descriptions. + python_class_name: Name of Custom Python Class to import for interface descriptions. + underlay_ethernet_interfaces: Path to Custom J2 template. + underlay_port_channel_interfaces: Path to Custom J2 template. + mlag_ethernet_interfaces: Path to Custom J2 template. + mlag_port_channel_interfaces: Path to Custom J2 template. + connected_endpoints_ethernet_interfaces: Path to Custom J2 template. + connected_endpoints_port_channel_interfaces: Path to Custom J2 template. + router_id_loopback_interface: Path to Custom J2 template. + vtep_loopback_interface: Path to Custom J2 template. + overlay_loopback_interface: Path to Custom J2 template. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "key": {"type": str}, + "type": {"type": str}, + "connected_endpoints": {"type": bool, "default": False}, + "default_evpn_role": {"type": str, "default": "none"}, + "default_ptp_priority1": {"type": int, "default": 127}, + "default_underlay_routing_protocol": {"type": str, "default": "ebgp"}, + "default_overlay_routing_protocol": {"type": str, "default": "ebgp"}, + "default_mpls_overlay_role": {"type": str}, + "default_overlay_address_families": {"type": DefaultOverlayAddressFamilies, "default": lambda cls: coerce_type(["evpn"], target_type=cls)}, + "default_evpn_encapsulation": {"type": str, "default": "vxlan"}, + "default_wan_role": {"type": str}, + "default_flow_tracker_type": {"type": str, "default": "sampled"}, + "mlag_support": {"type": bool, "default": False}, + "network_services": {"type": NetworkServices}, + "underlay_router": {"type": bool, "default": True}, + "uplink_type": {"type": str, "default": "p2p"}, + "vtep": {"type": bool, "default": False}, + "mpls_lsr": {"type": bool, "default": False}, + "ip_addressing": {"type": IpAddressing}, + "interface_descriptions": {"type": InterfaceDescriptions}, + "cv_tags_topology_type": {"type": str}, + "_custom_data": {"type": dict}, + } + key: str + type: str | None + """Type value matching this node_type_key.""" + connected_endpoints: bool + """ + Are endpoints connected to this node type. + + Default value: `False` + """ + default_evpn_role: Literal["none", "client", "server"] + """ + Default evpn_role. Can be overridden in topology vars. + + Default value: `"none"` + """ + default_ptp_priority1: int + """ + Default PTP priority 1 + + Default value: `127` + """ + default_underlay_routing_protocol: Literal["ebgp", "ospf", "ospf-ldp", "isis", "isis-sr", "isis-ldp", "isis-sr-ldp", "none"] + """ + Set the default underlay routing_protocol. + Can be overridden by setting "underlay_routing_protocol" + host/group_vars. + + Default value: `"ebgp"` + """ + default_overlay_routing_protocol: Literal["ebgp", "ibgp", "her", "cvx", "none"] + """ + Set the default overlay routing_protocol. + Can be overridden by setting "overlay_routing_protocol" + host/group_vars. + + Default value: `"ebgp"` + """ + default_mpls_overlay_role: Literal["client", "server", "none"] | None + """ + Set the default mpls overlay role. + Acting role in overlay control plane. + """ + default_overlay_address_families: DefaultOverlayAddressFamilies + """ + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["evpn"], target_type=cls)` + """ + default_evpn_encapsulation: Literal["mpls", "vxlan"] + """ + Set the default evpn encapsulation. + + Default value: `"vxlan"` + """ + default_wan_role: Literal["client", "server"] | None + """ + Set the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + """ + default_flow_tracker_type: Literal["sampled", "hardware"] + """ + Set the default flow tracker type. + + Default value: `"sampled"` + """ + mlag_support: bool + """ + Can this node type support mlag. + + Default value: `False` + """ + network_services: NetworkServices + """ + Will network services be deployed on this node type. + + Subclass of AvdModel. + """ + underlay_router: bool + """ + Is this node type a L3 device. + + Default value: `True` + """ + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] + """ + `uplink_type` must be `p2p`, `p2p-vrfs` or `lan` if `vtep` or `underlay_router` is true. + + For + `p2p-vrfs`, the uplinks are configured as L3 interfaces with a subinterface for each VRF + in + `network_services` present on both the uplink and the downlink switch. + The subinterface ID is the + `vrf_id`. + 'underlay_router' and 'network_services.l3' must be set to true. + VRF `default` is always + configured on the physical interface using the underlay routing protocol. + All subinterfaces use the + same IP address as the physical interface. + Multicast is not supported. + Only BGP is supported for + subinterfaces. + + For `lan`, a single uplink interface is supported and will be configured as an L3 + Interface with + subinterfaces for each SVI defined under the VRFs in `network_services` as long as + the uplink switch also + has the VLAN permitted by tag/tenant filtering. + + Default value: `"p2p"` + """ + vtep: bool + """ + Is this switch an EVPN VTEP. + + Default value: `False` + """ + mpls_lsr: bool + """ + Is this switch an MPLS LSR. + + Default value: `False` + """ + ip_addressing: IpAddressing + """ + Override ip_addressing templates. + + Subclass of AvdModel. + """ + interface_descriptions: InterfaceDescriptions + """ + Override interface_descriptions templates. + If description templates use Jinja2, they have to strip + whitespaces using {%- -%} on any code blocks. + + + Subclass of AvdModel. + """ + cv_tags_topology_type: Literal["leaf", "spine", "core", "edge"] | None + """ + PREVIEW: This key is currently not supported + Type that CloudVision should use when generating the + Topology. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + key: str | UndefinedType = Undefined, + type: str | None | UndefinedType = Undefined, + connected_endpoints: bool | UndefinedType = Undefined, + default_evpn_role: Literal["none", "client", "server"] | UndefinedType = Undefined, + default_ptp_priority1: int | UndefinedType = Undefined, + default_underlay_routing_protocol: Literal["ebgp", "ospf", "ospf-ldp", "isis", "isis-sr", "isis-ldp", "isis-sr-ldp", "none"] + | UndefinedType = Undefined, + default_overlay_routing_protocol: Literal["ebgp", "ibgp", "her", "cvx", "none"] | UndefinedType = Undefined, + default_mpls_overlay_role: Literal["client", "server", "none"] | None | UndefinedType = Undefined, + default_overlay_address_families: DefaultOverlayAddressFamilies | UndefinedType = Undefined, + default_evpn_encapsulation: Literal["mpls", "vxlan"] | UndefinedType = Undefined, + default_wan_role: Literal["client", "server"] | None | UndefinedType = Undefined, + default_flow_tracker_type: Literal["sampled", "hardware"] | UndefinedType = Undefined, + mlag_support: bool | UndefinedType = Undefined, + network_services: NetworkServices | UndefinedType = Undefined, + underlay_router: bool | UndefinedType = Undefined, + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | UndefinedType = Undefined, + vtep: bool | UndefinedType = Undefined, + mpls_lsr: bool | UndefinedType = Undefined, + ip_addressing: IpAddressing | UndefinedType = Undefined, + interface_descriptions: InterfaceDescriptions | UndefinedType = Undefined, + cv_tags_topology_type: Literal["leaf", "spine", "core", "edge"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CustomNodeTypeKeysItem. + + + Subclass of AvdModel. + + Args: + key: key + type: Type value matching this node_type_key. + connected_endpoints: Are endpoints connected to this node type. + default_evpn_role: Default evpn_role. Can be overridden in topology vars. + default_ptp_priority1: Default PTP priority 1 + default_underlay_routing_protocol: + Set the default underlay routing_protocol. + Can be overridden by setting "underlay_routing_protocol" + host/group_vars. + default_overlay_routing_protocol: + Set the default overlay routing_protocol. + Can be overridden by setting "overlay_routing_protocol" + host/group_vars. + default_mpls_overlay_role: + Set the default mpls overlay role. + Acting role in overlay control plane. + default_overlay_address_families: + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + default_evpn_encapsulation: Set the default evpn encapsulation. + default_wan_role: + Set the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + default_flow_tracker_type: Set the default flow tracker type. + mlag_support: Can this node type support mlag. + network_services: + Will network services be deployed on this node type. + + Subclass of AvdModel. + underlay_router: Is this node type a L3 device. + uplink_type: + `uplink_type` must be `p2p`, `p2p-vrfs` or `lan` if `vtep` or `underlay_router` is true. + + For + `p2p-vrfs`, the uplinks are configured as L3 interfaces with a subinterface for each VRF + in + `network_services` present on both the uplink and the downlink switch. + The subinterface ID is the + `vrf_id`. + 'underlay_router' and 'network_services.l3' must be set to true. + VRF `default` is always + configured on the physical interface using the underlay routing protocol. + All subinterfaces use the + same IP address as the physical interface. + Multicast is not supported. + Only BGP is supported for + subinterfaces. + + For `lan`, a single uplink interface is supported and will be configured as an L3 + Interface with + subinterfaces for each SVI defined under the VRFs in `network_services` as long as + the uplink switch also + has the VLAN permitted by tag/tenant filtering. + vtep: Is this switch an EVPN VTEP. + mpls_lsr: Is this switch an MPLS LSR. + ip_addressing: + Override ip_addressing templates. + + Subclass of AvdModel. + interface_descriptions: + Override interface_descriptions templates. + If description templates use Jinja2, they have to strip + whitespaces using {%- -%} on any code blocks. + + + Subclass of AvdModel. + cv_tags_topology_type: + PREVIEW: This key is currently not supported + Type that CloudVision should use when generating the + Topology. + _custom_data: _custom_data + + """ + + class CustomNodeTypeKeys(AvdIndexedList[str, CustomNodeTypeKeysItem]): + """Subclass of AvdIndexedList with `CustomNodeTypeKeysItem` items. Primary key is `key` (`str`).""" + + _primary_key: ClassVar[str] = "key" + + CustomNodeTypeKeys._item_type = CustomNodeTypeKeysItem + + class NodeTypeKeysItem(AvdModel): + """Subclass of AvdModel.""" + + class DefaultOverlayAddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DefaultOverlayAddressFamilies._item_type = str + + class NetworkServices(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "l1": {"type": bool, "default": False}, + "l2": {"type": bool, "default": False}, + "l3": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + l1: bool + """ + ?? + + Default value: `False` + """ + l2: bool + """ + Vlans + + Default value: `False` + """ + l3: bool + """ + VRFs, SVIs (if l2 is true). + Only supported with underlay_router. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + l1: bool | UndefinedType = Undefined, + l2: bool | UndefinedType = Undefined, + l3: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NetworkServices. + + + Subclass of AvdModel. + + Args: + l1: ?? + l2: Vlans + l3: + VRFs, SVIs (if l2 is true). + Only supported with underlay_router. + _custom_data: _custom_data + + """ + + class IpAddressing(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "python_module": {"type": str}, + "python_class_name": {"type": str, "default": "AvdIpAddressing"}, + "router_id": {"type": str}, + "router_id_ipv6": {"type": str}, + "mlag_ip_primary": {"type": str}, + "mlag_ip_secondary": {"type": str}, + "mlag_l3_ip_primary": {"type": str}, + "mlag_l3_ip_secondary": {"type": str}, + "mlag_ibgp_peering_ip_primary": {"type": str}, + "mlag_ibgp_peering_ip_secondary": {"type": str}, + "p2p_uplinks_ip": {"type": str}, + "p2p_uplinks_peer_ip": {"type": str}, + "vtep_ip_mlag": {"type": str}, + "vtep_ip": {"type": str}, + "_custom_data": {"type": dict}, + } + python_module: str | None + """Custom Python Module to import for IP addressing.""" + python_class_name: str + """ + Name of Custom Python Class to import for IP addressing. + + Default value: `"AvdIpAddressing"` + """ + router_id: str | None + """Path to Custom J2 template.""" + router_id_ipv6: str | None + """Path to Custom J2 template.""" + mlag_ip_primary: str | None + """Path to Custom J2 template.""" + mlag_ip_secondary: str | None + """Path to Custom J2 template.""" + mlag_l3_ip_primary: str | None + """Path to Custom J2 template.""" + mlag_l3_ip_secondary: str | None + """Path to Custom J2 template.""" + mlag_ibgp_peering_ip_primary: str | None + """Path to Custom J2 template.""" + mlag_ibgp_peering_ip_secondary: str | None + """Path to Custom J2 template.""" + p2p_uplinks_ip: str | None + """Path to Custom J2 template.""" + p2p_uplinks_peer_ip: str | None + """Path to Custom J2 template.""" + vtep_ip_mlag: str | None + """Path to Custom J2 template.""" + vtep_ip: str | None + """Path to Custom J2 template.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + python_module: str | None | UndefinedType = Undefined, + python_class_name: str | UndefinedType = Undefined, + router_id: str | None | UndefinedType = Undefined, + router_id_ipv6: str | None | UndefinedType = Undefined, + mlag_ip_primary: str | None | UndefinedType = Undefined, + mlag_ip_secondary: str | None | UndefinedType = Undefined, + mlag_l3_ip_primary: str | None | UndefinedType = Undefined, + mlag_l3_ip_secondary: str | None | UndefinedType = Undefined, + mlag_ibgp_peering_ip_primary: str | None | UndefinedType = Undefined, + mlag_ibgp_peering_ip_secondary: str | None | UndefinedType = Undefined, + p2p_uplinks_ip: str | None | UndefinedType = Undefined, + p2p_uplinks_peer_ip: str | None | UndefinedType = Undefined, + vtep_ip_mlag: str | None | UndefinedType = Undefined, + vtep_ip: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpAddressing. + + + Subclass of AvdModel. + + Args: + python_module: Custom Python Module to import for IP addressing. + python_class_name: Name of Custom Python Class to import for IP addressing. + router_id: Path to Custom J2 template. + router_id_ipv6: Path to Custom J2 template. + mlag_ip_primary: Path to Custom J2 template. + mlag_ip_secondary: Path to Custom J2 template. + mlag_l3_ip_primary: Path to Custom J2 template. + mlag_l3_ip_secondary: Path to Custom J2 template. + mlag_ibgp_peering_ip_primary: Path to Custom J2 template. + mlag_ibgp_peering_ip_secondary: Path to Custom J2 template. + p2p_uplinks_ip: Path to Custom J2 template. + p2p_uplinks_peer_ip: Path to Custom J2 template. + vtep_ip_mlag: Path to Custom J2 template. + vtep_ip: Path to Custom J2 template. + _custom_data: _custom_data + + """ + + class InterfaceDescriptions(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "python_module": {"type": str}, + "python_class_name": {"type": str, "default": "AvdInterfaceDescriptions"}, + "underlay_ethernet_interfaces": {"type": str}, + "underlay_port_channel_interfaces": {"type": str}, + "mlag_ethernet_interfaces": {"type": str}, + "mlag_port_channel_interfaces": {"type": str}, + "connected_endpoints_ethernet_interfaces": {"type": str}, + "connected_endpoints_port_channel_interfaces": {"type": str}, + "router_id_loopback_interface": {"type": str}, + "vtep_loopback_interface": {"type": str}, + "overlay_loopback_interface": {"type": str}, + "_custom_data": {"type": dict}, + } + python_module: str | None + """Custom Python Module to import for interface descriptions.""" + python_class_name: str + """ + Name of Custom Python Class to import for interface descriptions. + + Default value: `"AvdInterfaceDescriptions"` + """ + underlay_ethernet_interfaces: str | None + """Path to Custom J2 template.""" + underlay_port_channel_interfaces: str | None + """Path to Custom J2 template.""" + mlag_ethernet_interfaces: str | None + """Path to Custom J2 template.""" + mlag_port_channel_interfaces: str | None + """Path to Custom J2 template.""" + connected_endpoints_ethernet_interfaces: str | None + """Path to Custom J2 template.""" + connected_endpoints_port_channel_interfaces: str | None + """Path to Custom J2 template.""" + router_id_loopback_interface: str | None + """Path to Custom J2 template.""" + vtep_loopback_interface: str | None + """Path to Custom J2 template.""" + overlay_loopback_interface: str | None + """Path to Custom J2 template.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + python_module: str | None | UndefinedType = Undefined, + python_class_name: str | UndefinedType = Undefined, + underlay_ethernet_interfaces: str | None | UndefinedType = Undefined, + underlay_port_channel_interfaces: str | None | UndefinedType = Undefined, + mlag_ethernet_interfaces: str | None | UndefinedType = Undefined, + mlag_port_channel_interfaces: str | None | UndefinedType = Undefined, + connected_endpoints_ethernet_interfaces: str | None | UndefinedType = Undefined, + connected_endpoints_port_channel_interfaces: str | None | UndefinedType = Undefined, + router_id_loopback_interface: str | None | UndefinedType = Undefined, + vtep_loopback_interface: str | None | UndefinedType = Undefined, + overlay_loopback_interface: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + InterfaceDescriptions. + + + Subclass of AvdModel. + + Args: + python_module: Custom Python Module to import for interface descriptions. + python_class_name: Name of Custom Python Class to import for interface descriptions. + underlay_ethernet_interfaces: Path to Custom J2 template. + underlay_port_channel_interfaces: Path to Custom J2 template. + mlag_ethernet_interfaces: Path to Custom J2 template. + mlag_port_channel_interfaces: Path to Custom J2 template. + connected_endpoints_ethernet_interfaces: Path to Custom J2 template. + connected_endpoints_port_channel_interfaces: Path to Custom J2 template. + router_id_loopback_interface: Path to Custom J2 template. + vtep_loopback_interface: Path to Custom J2 template. + overlay_loopback_interface: Path to Custom J2 template. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "key": {"type": str}, + "type": {"type": str}, + "connected_endpoints": {"type": bool, "default": False}, + "default_evpn_role": {"type": str, "default": "none"}, + "default_ptp_priority1": {"type": int, "default": 127}, + "default_underlay_routing_protocol": {"type": str, "default": "ebgp"}, + "default_overlay_routing_protocol": {"type": str, "default": "ebgp"}, + "default_mpls_overlay_role": {"type": str}, + "default_overlay_address_families": {"type": DefaultOverlayAddressFamilies, "default": lambda cls: coerce_type(["evpn"], target_type=cls)}, + "default_evpn_encapsulation": {"type": str, "default": "vxlan"}, + "default_wan_role": {"type": str}, + "default_flow_tracker_type": {"type": str, "default": "sampled"}, + "mlag_support": {"type": bool, "default": False}, + "network_services": {"type": NetworkServices}, + "underlay_router": {"type": bool, "default": True}, + "uplink_type": {"type": str, "default": "p2p"}, + "vtep": {"type": bool, "default": False}, + "mpls_lsr": {"type": bool, "default": False}, + "ip_addressing": {"type": IpAddressing}, + "interface_descriptions": {"type": InterfaceDescriptions}, + "cv_tags_topology_type": {"type": str}, + "_custom_data": {"type": dict}, + } + key: str + type: str | None + """Type value matching this node_type_key.""" + connected_endpoints: bool + """ + Are endpoints connected to this node type. + + Default value: `False` + """ + default_evpn_role: Literal["none", "client", "server"] + """ + Default evpn_role. Can be overridden in topology vars. + + Default value: `"none"` + """ + default_ptp_priority1: int + """ + Default PTP priority 1 + + Default value: `127` + """ + default_underlay_routing_protocol: Literal["ebgp", "ospf", "ospf-ldp", "isis", "isis-sr", "isis-ldp", "isis-sr-ldp", "none"] + """ + Set the default underlay routing_protocol. + Can be overridden by setting "underlay_routing_protocol" + host/group_vars. + + Default value: `"ebgp"` + """ + default_overlay_routing_protocol: Literal["ebgp", "ibgp", "her", "cvx", "none"] + """ + Set the default overlay routing_protocol. + Can be overridden by setting "overlay_routing_protocol" + host/group_vars. + + Default value: `"ebgp"` + """ + default_mpls_overlay_role: Literal["client", "server", "none"] | None + """ + Set the default mpls overlay role. + Acting role in overlay control plane. + """ + default_overlay_address_families: DefaultOverlayAddressFamilies + """ + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["evpn"], target_type=cls)` + """ + default_evpn_encapsulation: Literal["mpls", "vxlan"] + """ + Set the default evpn encapsulation. + + Default value: `"vxlan"` + """ + default_wan_role: Literal["client", "server"] | None + """ + Set the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + """ + default_flow_tracker_type: Literal["sampled", "hardware"] + """ + Set the default flow tracker type. + + Default value: `"sampled"` + """ + mlag_support: bool + """ + Can this node type support mlag. + + Default value: `False` + """ + network_services: NetworkServices + """ + Will network services be deployed on this node type. + + Subclass of AvdModel. + """ + underlay_router: bool + """ + Is this node type a L3 device. + + Default value: `True` + """ + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] + """ + `uplink_type` must be `p2p`, `p2p-vrfs` or `lan` if `vtep` or `underlay_router` is true. + + For + `p2p-vrfs`, the uplinks are configured as L3 interfaces with a subinterface for each VRF + in + `network_services` present on both the uplink and the downlink switch. + The subinterface ID is the + `vrf_id`. + 'underlay_router' and 'network_services.l3' must be set to true. + VRF `default` is always + configured on the physical interface using the underlay routing protocol. + All subinterfaces use the + same IP address as the physical interface. + Multicast is not supported. + Only BGP is supported for + subinterfaces. + + For `lan`, a single uplink interface is supported and will be configured as an L3 + Interface with + subinterfaces for each SVI defined under the VRFs in `network_services` as long as + the uplink switch also + has the VLAN permitted by tag/tenant filtering. + + Default value: `"p2p"` + """ + vtep: bool + """ + Is this switch an EVPN VTEP. + + Default value: `False` + """ + mpls_lsr: bool + """ + Is this switch an MPLS LSR. + + Default value: `False` + """ + ip_addressing: IpAddressing + """ + Override ip_addressing templates. + + Subclass of AvdModel. + """ + interface_descriptions: InterfaceDescriptions + """ + Override interface_descriptions templates. + If description templates use Jinja2, they have to strip + whitespaces using {%- -%} on any code blocks. + + + Subclass of AvdModel. + """ + cv_tags_topology_type: Literal["leaf", "spine", "core", "edge"] | None + """ + PREVIEW: This key is currently not supported + Type that CloudVision should use when generating the + Topology. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + key: str | UndefinedType = Undefined, + type: str | None | UndefinedType = Undefined, + connected_endpoints: bool | UndefinedType = Undefined, + default_evpn_role: Literal["none", "client", "server"] | UndefinedType = Undefined, + default_ptp_priority1: int | UndefinedType = Undefined, + default_underlay_routing_protocol: Literal["ebgp", "ospf", "ospf-ldp", "isis", "isis-sr", "isis-ldp", "isis-sr-ldp", "none"] + | UndefinedType = Undefined, + default_overlay_routing_protocol: Literal["ebgp", "ibgp", "her", "cvx", "none"] | UndefinedType = Undefined, + default_mpls_overlay_role: Literal["client", "server", "none"] | None | UndefinedType = Undefined, + default_overlay_address_families: DefaultOverlayAddressFamilies | UndefinedType = Undefined, + default_evpn_encapsulation: Literal["mpls", "vxlan"] | UndefinedType = Undefined, + default_wan_role: Literal["client", "server"] | None | UndefinedType = Undefined, + default_flow_tracker_type: Literal["sampled", "hardware"] | UndefinedType = Undefined, + mlag_support: bool | UndefinedType = Undefined, + network_services: NetworkServices | UndefinedType = Undefined, + underlay_router: bool | UndefinedType = Undefined, + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | UndefinedType = Undefined, + vtep: bool | UndefinedType = Undefined, + mpls_lsr: bool | UndefinedType = Undefined, + ip_addressing: IpAddressing | UndefinedType = Undefined, + interface_descriptions: InterfaceDescriptions | UndefinedType = Undefined, + cv_tags_topology_type: Literal["leaf", "spine", "core", "edge"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NodeTypeKeysItem. + + + Subclass of AvdModel. + + Args: + key: key + type: Type value matching this node_type_key. + connected_endpoints: Are endpoints connected to this node type. + default_evpn_role: Default evpn_role. Can be overridden in topology vars. + default_ptp_priority1: Default PTP priority 1 + default_underlay_routing_protocol: + Set the default underlay routing_protocol. + Can be overridden by setting "underlay_routing_protocol" + host/group_vars. + default_overlay_routing_protocol: + Set the default overlay routing_protocol. + Can be overridden by setting "overlay_routing_protocol" + host/group_vars. + default_mpls_overlay_role: + Set the default mpls overlay role. + Acting role in overlay control plane. + default_overlay_address_families: + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + default_evpn_encapsulation: Set the default evpn encapsulation. + default_wan_role: + Set the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + default_flow_tracker_type: Set the default flow tracker type. + mlag_support: Can this node type support mlag. + network_services: + Will network services be deployed on this node type. + + Subclass of AvdModel. + underlay_router: Is this node type a L3 device. + uplink_type: + `uplink_type` must be `p2p`, `p2p-vrfs` or `lan` if `vtep` or `underlay_router` is true. + + For + `p2p-vrfs`, the uplinks are configured as L3 interfaces with a subinterface for each VRF + in + `network_services` present on both the uplink and the downlink switch. + The subinterface ID is the + `vrf_id`. + 'underlay_router' and 'network_services.l3' must be set to true. + VRF `default` is always + configured on the physical interface using the underlay routing protocol. + All subinterfaces use the + same IP address as the physical interface. + Multicast is not supported. + Only BGP is supported for + subinterfaces. + + For `lan`, a single uplink interface is supported and will be configured as an L3 + Interface with + subinterfaces for each SVI defined under the VRFs in `network_services` as long as + the uplink switch also + has the VLAN permitted by tag/tenant filtering. + vtep: Is this switch an EVPN VTEP. + mpls_lsr: Is this switch an MPLS LSR. + ip_addressing: + Override ip_addressing templates. + + Subclass of AvdModel. + interface_descriptions: + Override interface_descriptions templates. + If description templates use Jinja2, they have to strip + whitespaces using {%- -%} on any code blocks. + + + Subclass of AvdModel. + cv_tags_topology_type: + PREVIEW: This key is currently not supported + Type that CloudVision should use when generating the + Topology. + _custom_data: _custom_data + + """ + + class NodeTypeKeys(AvdIndexedList[str, NodeTypeKeysItem]): + """Subclass of AvdIndexedList with `NodeTypeKeysItem` items. Primary key is `key` (`str`).""" + + _primary_key: ClassVar[str] = "key" + + NodeTypeKeys._item_type = NodeTypeKeysItem + + class NtpSettings(AvdModel): + """Subclass of AvdModel.""" + + class ServersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "burst": {"type": bool}, + "iburst": {"type": bool}, + "key": {"type": int}, + "maxpoll": {"type": int}, + "minpoll": {"type": int}, + "version": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str | None + """IP or hostname e.g., 2.2.2.55, 2001:db8::55, ie.pool.ntp.org.""" + burst: bool | None + iburst: bool | None + key: int | None + maxpoll: int | None + """Value of maxpoll between 3 - 17 (Logarithmic).""" + minpoll: int | None + """Value of minpoll between 3 - 17 (Logarithmic).""" + version: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + burst: bool | None | UndefinedType = Undefined, + iburst: bool | None | UndefinedType = Undefined, + key: int | None | UndefinedType = Undefined, + maxpoll: int | None | UndefinedType = Undefined, + minpoll: int | None | UndefinedType = Undefined, + version: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ServersItem. + + + Subclass of AvdModel. + + Args: + name: IP or hostname e.g., 2.2.2.55, 2001:db8::55, ie.pool.ntp.org. + burst: burst + iburst: iburst + key: key + maxpoll: Value of maxpoll between 3 - 17 (Logarithmic). + minpoll: Value of minpoll between 3 - 17 (Logarithmic). + version: version + _custom_data: _custom_data + + """ + + class Servers(AvdList[ServersItem]): + """Subclass of AvdList with `ServersItem` items.""" + + Servers._item_type = ServersItem + + class AuthenticationKeys(EosCliConfigGen.Ntp.AuthenticationKeys): + pass + + _fields: ClassVar[dict] = { + "server_vrf": {"type": str}, + "servers": {"type": Servers}, + "authenticate": {"type": bool}, + "authenticate_servers_only": {"type": bool}, + "authentication_keys": {"type": AuthenticationKeys}, + "trusted_keys": {"type": str}, + "_custom_data": {"type": dict}, + } + server_vrf: str | None + """ + EOS only supports NTP servers in one VRF, so this VRF is used for all NTP servers and one local- + interface. + - `use_mgmt_interface_vrf` will configure the NTP server(s) under the VRF set with + `mgmt_interface_vrf` and set the `mgmt_interface` as NTP local-interface. + An error will be raised + if `mgmt_ip` or `ipv6_mgmt_ip` are not configured for the device. + - `use_inband_mgmt_vrf` will + configure the NTP server(s) under the VRF set with `inband_mgmt_vrf` and set the + `inband_mgmt_interface` as NTP local-interface. + An error will be raised if inband management is + not configured for the device. + - Any other string will be used directly as the VRF name but local + interface must be set with `custom_structured_configuration_ntp` if needed. + If not set, the VRF is + automatically picked up from the global setting `default_mgmt_method`. + """ + servers: Servers + """ + The first server is always set as "preferred". + + Subclass of AvdList with `ServersItem` items. + """ + authenticate: bool | None + authenticate_servers_only: bool | None + authentication_keys: AuthenticationKeys + trusted_keys: str | None + """List of trusted-keys as string ex. 10-12,15.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + server_vrf: str | None | UndefinedType = Undefined, + servers: Servers | UndefinedType = Undefined, + authenticate: bool | None | UndefinedType = Undefined, + authenticate_servers_only: bool | None | UndefinedType = Undefined, + authentication_keys: AuthenticationKeys | UndefinedType = Undefined, + trusted_keys: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NtpSettings. + + + Subclass of AvdModel. + + Args: + server_vrf: + EOS only supports NTP servers in one VRF, so this VRF is used for all NTP servers and one local- + interface. + - `use_mgmt_interface_vrf` will configure the NTP server(s) under the VRF set with + `mgmt_interface_vrf` and set the `mgmt_interface` as NTP local-interface. + An error will be raised + if `mgmt_ip` or `ipv6_mgmt_ip` are not configured for the device. + - `use_inband_mgmt_vrf` will + configure the NTP server(s) under the VRF set with `inband_mgmt_vrf` and set the + `inband_mgmt_interface` as NTP local-interface. + An error will be raised if inband management is + not configured for the device. + - Any other string will be used directly as the VRF name but local + interface must be set with `custom_structured_configuration_ntp` if needed. + If not set, the VRF is + automatically picked up from the global setting `default_mgmt_method`. + servers: + The first server is always set as "preferred". + + Subclass of AvdList with `ServersItem` items. + authenticate: authenticate + authenticate_servers_only: authenticate_servers_only + authentication_keys: authentication_keys + trusted_keys: List of trusted-keys as string ex. 10-12,15. + _custom_data: _custom_data + + """ + + class OverlayCvxServers(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + OverlayCvxServers._item_type = str + + class OverlayRdType(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "admin_subfield": {"type": str, "default": "router_id"}, + "admin_subfield_offset": {"type": int, "default": 0}, + "vrf_admin_subfield": {"type": str}, + "vrf_admin_subfield_offset": {"type": int}, + "vlan_assigned_number_subfield": {"type": str, "default": "mac_vrf_id"}, + "_custom_data": {"type": dict}, + } + admin_subfield: str + """ + The method for deriving RD Administrator subfield (first part of RD): + - 'router_id' means the IP + address of Loopback0. + - 'vtep_loopback' means the IP address of the VTEP loopback interface. + - + 'bgp_as' means the AS number of the device. + - 'switch_id' means the 'id' value of the device. + - Any + without mask. + - Integer between <0-65535>. + - Integer between <0-4294967295>. + - + 'overlay_loopback_ip' means the IP address of Loopback0. (deprecated - use 'router_id' instead) + + Default value: `"router_id"` + """ + admin_subfield_offset: int + """ + Offset can only be used if admin_subfield is an integer between <0-4294967295> or 'switch_id'. + Total + value of admin_subfield + admin_subfield_offset must be <= 4294967295. + + Default value: `0` + """ + vrf_admin_subfield: str | None + """ + The method for deriving RD Administrator subfield (first part of RD) for VRF services: + - 'router_id' + means the IP address of Loopback0. + - 'vtep_loopback' means the IP address of the VTEP loopback + interface. + - 'bgp_as' means the AS number of the device. + - 'switch_id' means the 'id' value of the + device. + - Any without mask. + - Integer between <0-65535>. + - Integer between + <0-4294967295>. + - 'overlay_loopback_ip' means the IP address of Loopback0. (deprecated - use + 'router_id' instead) + + 'vrf_admin_subfield' takes precedence for VRF RDs if set. Otherwise the + 'admin_subfield' value will be used. + """ + vrf_admin_subfield_offset: int | None + """ + Offset can only be used if 'vrf_admin_subfield' is an integer between <0-4294967295> or 'switch_id'. + Total value of 'vrf_admin_subfield' + 'vrf_admin_subfield_offset' must be <= 4294967295. + 'vrf_admin_subfield_offset' takes precedence for VRF RDs if set. Otherwise the + 'admin_subfield_offset' value will be used. + """ + vlan_assigned_number_subfield: Literal["mac_vrf_id", "mac_vrf_vni", "vlan_id"] + """ + The method for deriving RD Assigned Number subfield for VLAN services (second part of RD): + - + 'mac_vrf_id' means `(mac_vrf_id_base or mac_vrf_vni_base) + vlan_id`. + - 'mac_vrf_vni' means + `(mac_vrf_vni_base or mac_vrf_id_base) + vlan_id`. + - 'vlan_id' will only use the 'vlan_id' and + ignores all base values. + + These methods can be overridden per VLAN if either 'rd_override', + 'rt_override' or 'vni_override' is set (preferred in this order). + + Default value: `"mac_vrf_id"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + admin_subfield: str | UndefinedType = Undefined, + admin_subfield_offset: int | UndefinedType = Undefined, + vrf_admin_subfield: str | None | UndefinedType = Undefined, + vrf_admin_subfield_offset: int | None | UndefinedType = Undefined, + vlan_assigned_number_subfield: Literal["mac_vrf_id", "mac_vrf_vni", "vlan_id"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + OverlayRdType. + + + Subclass of AvdModel. + + Args: + admin_subfield: + The method for deriving RD Administrator subfield (first part of RD): + - 'router_id' means the IP + address of Loopback0. + - 'vtep_loopback' means the IP address of the VTEP loopback interface. + - + 'bgp_as' means the AS number of the device. + - 'switch_id' means the 'id' value of the device. + - Any + without mask. + - Integer between <0-65535>. + - Integer between <0-4294967295>. + - + 'overlay_loopback_ip' means the IP address of Loopback0. (deprecated - use 'router_id' instead) + admin_subfield_offset: + Offset can only be used if admin_subfield is an integer between <0-4294967295> or 'switch_id'. + Total + value of admin_subfield + admin_subfield_offset must be <= 4294967295. + vrf_admin_subfield: + The method for deriving RD Administrator subfield (first part of RD) for VRF services: + - 'router_id' + means the IP address of Loopback0. + - 'vtep_loopback' means the IP address of the VTEP loopback + interface. + - 'bgp_as' means the AS number of the device. + - 'switch_id' means the 'id' value of the + device. + - Any without mask. + - Integer between <0-65535>. + - Integer between + <0-4294967295>. + - 'overlay_loopback_ip' means the IP address of Loopback0. (deprecated - use + 'router_id' instead) + + 'vrf_admin_subfield' takes precedence for VRF RDs if set. Otherwise the + 'admin_subfield' value will be used. + vrf_admin_subfield_offset: + Offset can only be used if 'vrf_admin_subfield' is an integer between <0-4294967295> or 'switch_id'. + Total value of 'vrf_admin_subfield' + 'vrf_admin_subfield_offset' must be <= 4294967295. + 'vrf_admin_subfield_offset' takes precedence for VRF RDs if set. Otherwise the + 'admin_subfield_offset' value will be used. + vlan_assigned_number_subfield: + The method for deriving RD Assigned Number subfield for VLAN services (second part of RD): + - + 'mac_vrf_id' means `(mac_vrf_id_base or mac_vrf_vni_base) + vlan_id`. + - 'mac_vrf_vni' means + `(mac_vrf_vni_base or mac_vrf_id_base) + vlan_id`. + - 'vlan_id' will only use the 'vlan_id' and + ignores all base values. + + These methods can be overridden per VLAN if either 'rd_override', + 'rt_override' or 'vni_override' is set (preferred in this order). + _custom_data: _custom_data + + """ + + class OverlayRtType(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "admin_subfield": {"type": str, "default": "vrf_id"}, + "vrf_admin_subfield": {"type": str}, + "vlan_assigned_number_subfield": {"type": str, "default": "mac_vrf_id"}, + "_custom_data": {"type": dict}, + } + admin_subfield: str + """ + The method for deriving RT Administrator subfield (first part of RT): + - 'vrf_id' means + `(mac_vrf_id_base or mac_vrf_vni_base) + vlan_id` for VLANs, `(vrf_id or vrf_vni)` for VRFs and `id` + for bundles defined under 'evpn_vlan_bundles'. + - 'vrf_vni' means `(mac_vrf_vni_base or + mac_vrf_id_base) + vlan_id` for VLANs, `(vrf_vni or vrf_id)` for VRFs and `id` for bundles defined + under 'evpn_vlan_bundles'. + - 'id' means `vlan_id` for VLANs, `(vrf_id or vrf_vni)` for VRFs and `id` + for bundles defined under 'evpn_vlan_bundles'. + - 'bgp_as' means the AS number of the device. + - + Integer between <0-65535>. + - Integer between <0-4294967295>. + + The 'vrf_id' and 'vrf_vni' methods can + be overridden per VLAN if either 'rt_override' or 'vni_override' is set (preferred in this order). + The 'vrf_id', 'vrf_vni' and 'id' methods can be overridden per bundle defined under + `evpn_vlan_bundles` using 'rt_override'. + + Default value: `"vrf_id"` + """ + vrf_admin_subfield: str | None + """ + The method for deriving RT Administrator subfield (first part of RT) for VRF services: + - 'id' means + `(vrf_id or vrf_vni)`. + - 'vrf_id' means `(vrf_id or vrf_vni)`. + - 'vrf_vni' means `(vrf_vni or + vrf_id)`. + - 'bgp_as' means the AS number of the device. + - Integer between <0-65535>. + - Integer + between <0-4294967295>. + + 'vrf_admin_subfield' takes precedence for VRF RDs if set. Otherwise the + 'admin_subfield' value will be used. + """ + vlan_assigned_number_subfield: Literal["mac_vrf_id", "mac_vrf_vni", "vlan_id"] + """ + The method for deriving RT Assigned Number subfield for VLAN services (second part of RT): + - + 'mac_vrf_id' means `(mac_vrf_id_base or mac_vrf_vni_base) + vlan_id`. + - 'mac_vrf_vni' means + `(mac_vrf_vni_base or mac_vrf_id_base) + vlan_id`. + - 'vlan_id' will only use the 'vlan_id' and + ignores all base values. + + These methods can be overridden per VLAN if either 'rt_override' or + 'vni_override' is set (preferred in this order). + + Default value: `"mac_vrf_id"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + admin_subfield: str | UndefinedType = Undefined, + vrf_admin_subfield: str | None | UndefinedType = Undefined, + vlan_assigned_number_subfield: Literal["mac_vrf_id", "mac_vrf_vni", "vlan_id"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + OverlayRtType. + + + Subclass of AvdModel. + + Args: + admin_subfield: + The method for deriving RT Administrator subfield (first part of RT): + - 'vrf_id' means + `(mac_vrf_id_base or mac_vrf_vni_base) + vlan_id` for VLANs, `(vrf_id or vrf_vni)` for VRFs and `id` + for bundles defined under 'evpn_vlan_bundles'. + - 'vrf_vni' means `(mac_vrf_vni_base or + mac_vrf_id_base) + vlan_id` for VLANs, `(vrf_vni or vrf_id)` for VRFs and `id` for bundles defined + under 'evpn_vlan_bundles'. + - 'id' means `vlan_id` for VLANs, `(vrf_id or vrf_vni)` for VRFs and `id` + for bundles defined under 'evpn_vlan_bundles'. + - 'bgp_as' means the AS number of the device. + - + Integer between <0-65535>. + - Integer between <0-4294967295>. + + The 'vrf_id' and 'vrf_vni' methods can + be overridden per VLAN if either 'rt_override' or 'vni_override' is set (preferred in this order). + The 'vrf_id', 'vrf_vni' and 'id' methods can be overridden per bundle defined under + `evpn_vlan_bundles` using 'rt_override'. + vrf_admin_subfield: + The method for deriving RT Administrator subfield (first part of RT) for VRF services: + - 'id' means + `(vrf_id or vrf_vni)`. + - 'vrf_id' means `(vrf_id or vrf_vni)`. + - 'vrf_vni' means `(vrf_vni or + vrf_id)`. + - 'bgp_as' means the AS number of the device. + - Integer between <0-65535>. + - Integer + between <0-4294967295>. + + 'vrf_admin_subfield' takes precedence for VRF RDs if set. Otherwise the + 'admin_subfield' value will be used. + vlan_assigned_number_subfield: + The method for deriving RT Assigned Number subfield for VLAN services (second part of RT): + - + 'mac_vrf_id' means `(mac_vrf_id_base or mac_vrf_vni_base) + vlan_id`. + - 'mac_vrf_vni' means + `(mac_vrf_vni_base or mac_vrf_id_base) + vlan_id`. + - 'vlan_id' will only use the 'vlan_id' and + ignores all base values. + + These methods can be overridden per VLAN if either 'rt_override' or + 'vni_override' is set (preferred in this order). + _custom_data: _custom_data + + """ + + class CustomPlatformSettingsItem(AvdModel): + """Subclass of AvdModel.""" + + class Platforms(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Platforms._item_type = str + + class ReloadDelay(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"mlag": {"type": int}, "non_mlag": {"type": int}, "_custom_data": {"type": dict}} + mlag: int | None + """In seconds.""" + non_mlag: int | None + """In seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mlag: int | None | UndefinedType = Undefined, + non_mlag: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ReloadDelay. + + + Subclass of AvdModel. + + Args: + mlag: In seconds. + non_mlag: In seconds. + _custom_data: _custom_data + + """ + + class FeatureSupport(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "queue_monitor_length_notify": {"type": bool, "default": True}, + "interface_storm_control": {"type": bool, "default": True}, + "poe": {"type": bool, "default": False}, + "per_interface_mtu": {"type": bool, "default": True}, + "bgp_update_wait_install": {"type": bool, "default": True}, + "bgp_update_wait_for_convergence": {"type": bool, "default": True}, + "_custom_data": {"type": dict}, + } + queue_monitor_length_notify: bool + """Default value: `True`""" + interface_storm_control: bool + """Default value: `True`""" + poe: bool + """Default value: `False`""" + per_interface_mtu: bool + """ + Support for configuration of per interface MTU for p2p links, MLAG SVIs and Network Services. + Effectively this means that all settings regarding interface MTU will be ignored if this is false. + Platforms without support for per interface MTU can use a single default interface MTU setting. Set + this via "default_interface_mtu" + + Default value: `True` + """ + bgp_update_wait_install: bool + """ + Disables FIB updates and route advertisement when the BGP instance is initiated until the BGP + convergence state is reached. + Can be overridden by setting "bgp_update_wait_install" + host/group_vars. + + Default value: `True` + """ + bgp_update_wait_for_convergence: bool + """ + Do not advertise reachability to a prefix until that prefix has been installed in hardware. + This + will eliminate any temporary black holes due to a BGP speaker advertising reachability to a prefix + that may not yet be installed into the forwarding plane. + Can be overridden by setting + "bgp_update_wait_for_convergence" host/group_vars. + + Default value: `True` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + queue_monitor_length_notify: bool | UndefinedType = Undefined, + interface_storm_control: bool | UndefinedType = Undefined, + poe: bool | UndefinedType = Undefined, + per_interface_mtu: bool | UndefinedType = Undefined, + bgp_update_wait_install: bool | UndefinedType = Undefined, + bgp_update_wait_for_convergence: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FeatureSupport. + + + Subclass of AvdModel. + + Args: + queue_monitor_length_notify: queue_monitor_length_notify + interface_storm_control: interface_storm_control + poe: poe + per_interface_mtu: + Support for configuration of per interface MTU for p2p links, MLAG SVIs and Network Services. + Effectively this means that all settings regarding interface MTU will be ignored if this is false. + Platforms without support for per interface MTU can use a single default interface MTU setting. Set + this via "default_interface_mtu" + bgp_update_wait_install: + Disables FIB updates and route advertisement when the BGP instance is initiated until the BGP + convergence state is reached. + Can be overridden by setting "bgp_update_wait_install" + host/group_vars. + bgp_update_wait_for_convergence: + Do not advertise reachability to a prefix until that prefix has been installed in hardware. + This + will eliminate any temporary black holes due to a BGP speaker advertising reachability to a prefix + that may not yet be installed into the forwarding plane. + Can be overridden by setting + "bgp_update_wait_for_convergence" host/group_vars. + _custom_data: _custom_data + + """ + + class SecurityEntropySources(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hardware": {"type": bool}, + "haveged": {"type": bool}, + "cpu_jitter": {"type": bool}, + "hardware_exclusive": {"type": bool}, + "_custom_data": {"type": dict}, + } + hardware: bool | None + """Use a hardware based source.""" + haveged: bool | None + """Use the HAVEGE algorithm.""" + cpu_jitter: bool | None + """Use the Jitter RNG algorithm of a CPU based source.""" + hardware_exclusive: bool | None + """Only use entropy from the hardware source.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hardware: bool | None | UndefinedType = Undefined, + haveged: bool | None | UndefinedType = Undefined, + cpu_jitter: bool | None | UndefinedType = Undefined, + hardware_exclusive: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SecurityEntropySources. + + + Subclass of AvdModel. + + Args: + hardware: Use a hardware based source. + haveged: Use the HAVEGE algorithm. + cpu_jitter: Use the Jitter RNG algorithm of a CPU based source. + hardware_exclusive: Only use entropy from the hardware source. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "platforms": {"type": Platforms}, + "trident_forwarding_table_partition": {"type": str}, + "reload_delay": {"type": ReloadDelay}, + "tcam_profile": {"type": str}, + "lag_hardware_only": {"type": bool}, + "default_interface_mtu": {"type": int}, + "p2p_uplinks_mtu": {"type": int}, + "feature_support": {"type": FeatureSupport}, + "management_interface": {"type": str, "default": "Management1"}, + "security_entropy_sources": {"type": SecurityEntropySources}, + "structured_config": {"type": StructuredConfig}, + "raw_eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + platforms: Platforms + """Subclass of AvdList with `str` items.""" + trident_forwarding_table_partition: str | None + """Only applied when evpn_multicast is true.""" + reload_delay: ReloadDelay + """Subclass of AvdModel.""" + tcam_profile: str | None + lag_hardware_only: bool | None + default_interface_mtu: int | None + """ + Default interface MTU configured on EOS under "interface defaults". + Takes precedence over the root + key "default_interface_mtu". + """ + p2p_uplinks_mtu: int | None + """ + Set MTU on point to point uplink interfaces. + Takes precedence over the root key "p2p_uplinks_mtu". + .uplink_mtu -> platform_settings.p2p_uplinks_mtu -> p2p_uplinks_mtu -> 9214. + """ + feature_support: FeatureSupport + """Subclass of AvdModel.""" + management_interface: str + """Default value: `"Management1"`""" + security_entropy_sources: SecurityEntropySources + """ + Entropy source improves the randomness of the numbers used to generate MACsec's cryptographic keys. + Subclass of AvdModel. + """ + structured_config: StructuredConfig + """ + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the root level of the final EOS configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + platforms: Platforms | UndefinedType = Undefined, + trident_forwarding_table_partition: str | None | UndefinedType = Undefined, + reload_delay: ReloadDelay | UndefinedType = Undefined, + tcam_profile: str | None | UndefinedType = Undefined, + lag_hardware_only: bool | None | UndefinedType = Undefined, + default_interface_mtu: int | None | UndefinedType = Undefined, + p2p_uplinks_mtu: int | None | UndefinedType = Undefined, + feature_support: FeatureSupport | UndefinedType = Undefined, + management_interface: str | UndefinedType = Undefined, + security_entropy_sources: SecurityEntropySources | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CustomPlatformSettingsItem. + + + Subclass of AvdModel. + + Args: + platforms: Subclass of AvdList with `str` items. + trident_forwarding_table_partition: Only applied when evpn_multicast is true. + reload_delay: Subclass of AvdModel. + tcam_profile: tcam_profile + lag_hardware_only: lag_hardware_only + default_interface_mtu: + Default interface MTU configured on EOS under "interface defaults". + Takes precedence over the root + key "default_interface_mtu". + p2p_uplinks_mtu: + Set MTU on point to point uplink interfaces. + Takes precedence over the root key "p2p_uplinks_mtu". + .uplink_mtu -> platform_settings.p2p_uplinks_mtu -> p2p_uplinks_mtu -> 9214. + feature_support: Subclass of AvdModel. + management_interface: management_interface + security_entropy_sources: + Entropy source improves the randomness of the numbers used to generate MACsec's cryptographic keys. + Subclass of AvdModel. + structured_config: + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the root level of the final EOS configuration. + _custom_data: _custom_data + + """ + + class CustomPlatformSettings(AvdList[CustomPlatformSettingsItem]): + """Subclass of AvdList with `CustomPlatformSettingsItem` items.""" + + CustomPlatformSettings._item_type = CustomPlatformSettingsItem + + class PlatformSettingsItem(AvdModel): + """Subclass of AvdModel.""" + + class Platforms(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Platforms._item_type = str + + class ReloadDelay(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"mlag": {"type": int}, "non_mlag": {"type": int}, "_custom_data": {"type": dict}} + mlag: int | None + """In seconds.""" + non_mlag: int | None + """In seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mlag: int | None | UndefinedType = Undefined, + non_mlag: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ReloadDelay. + + + Subclass of AvdModel. + + Args: + mlag: In seconds. + non_mlag: In seconds. + _custom_data: _custom_data + + """ + + class FeatureSupport(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "queue_monitor_length_notify": {"type": bool, "default": True}, + "interface_storm_control": {"type": bool, "default": True}, + "poe": {"type": bool, "default": False}, + "per_interface_mtu": {"type": bool, "default": True}, + "bgp_update_wait_install": {"type": bool, "default": True}, + "bgp_update_wait_for_convergence": {"type": bool, "default": True}, + "_custom_data": {"type": dict}, + } + queue_monitor_length_notify: bool + """Default value: `True`""" + interface_storm_control: bool + """Default value: `True`""" + poe: bool + """Default value: `False`""" + per_interface_mtu: bool + """ + Support for configuration of per interface MTU for p2p links, MLAG SVIs and Network Services. + Effectively this means that all settings regarding interface MTU will be ignored if this is false. + Platforms without support for per interface MTU can use a single default interface MTU setting. Set + this via "default_interface_mtu" + + Default value: `True` + """ + bgp_update_wait_install: bool + """ + Disables FIB updates and route advertisement when the BGP instance is initiated until the BGP + convergence state is reached. + Can be overridden by setting "bgp_update_wait_install" + host/group_vars. + + Default value: `True` + """ + bgp_update_wait_for_convergence: bool + """ + Do not advertise reachability to a prefix until that prefix has been installed in hardware. + This + will eliminate any temporary black holes due to a BGP speaker advertising reachability to a prefix + that may not yet be installed into the forwarding plane. + Can be overridden by setting + "bgp_update_wait_for_convergence" host/group_vars. + + Default value: `True` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + queue_monitor_length_notify: bool | UndefinedType = Undefined, + interface_storm_control: bool | UndefinedType = Undefined, + poe: bool | UndefinedType = Undefined, + per_interface_mtu: bool | UndefinedType = Undefined, + bgp_update_wait_install: bool | UndefinedType = Undefined, + bgp_update_wait_for_convergence: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FeatureSupport. + + + Subclass of AvdModel. + + Args: + queue_monitor_length_notify: queue_monitor_length_notify + interface_storm_control: interface_storm_control + poe: poe + per_interface_mtu: + Support for configuration of per interface MTU for p2p links, MLAG SVIs and Network Services. + Effectively this means that all settings regarding interface MTU will be ignored if this is false. + Platforms without support for per interface MTU can use a single default interface MTU setting. Set + this via "default_interface_mtu" + bgp_update_wait_install: + Disables FIB updates and route advertisement when the BGP instance is initiated until the BGP + convergence state is reached. + Can be overridden by setting "bgp_update_wait_install" + host/group_vars. + bgp_update_wait_for_convergence: + Do not advertise reachability to a prefix until that prefix has been installed in hardware. + This + will eliminate any temporary black holes due to a BGP speaker advertising reachability to a prefix + that may not yet be installed into the forwarding plane. + Can be overridden by setting + "bgp_update_wait_for_convergence" host/group_vars. + _custom_data: _custom_data + + """ + + class SecurityEntropySources(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hardware": {"type": bool}, + "haveged": {"type": bool}, + "cpu_jitter": {"type": bool}, + "hardware_exclusive": {"type": bool}, + "_custom_data": {"type": dict}, + } + hardware: bool | None + """Use a hardware based source.""" + haveged: bool | None + """Use the HAVEGE algorithm.""" + cpu_jitter: bool | None + """Use the Jitter RNG algorithm of a CPU based source.""" + hardware_exclusive: bool | None + """Only use entropy from the hardware source.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hardware: bool | None | UndefinedType = Undefined, + haveged: bool | None | UndefinedType = Undefined, + cpu_jitter: bool | None | UndefinedType = Undefined, + hardware_exclusive: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SecurityEntropySources. + + + Subclass of AvdModel. + + Args: + hardware: Use a hardware based source. + haveged: Use the HAVEGE algorithm. + cpu_jitter: Use the Jitter RNG algorithm of a CPU based source. + hardware_exclusive: Only use entropy from the hardware source. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "platforms": {"type": Platforms}, + "trident_forwarding_table_partition": {"type": str}, + "reload_delay": {"type": ReloadDelay}, + "tcam_profile": {"type": str}, + "lag_hardware_only": {"type": bool}, + "default_interface_mtu": {"type": int}, + "p2p_uplinks_mtu": {"type": int}, + "feature_support": {"type": FeatureSupport}, + "management_interface": {"type": str, "default": "Management1"}, + "security_entropy_sources": {"type": SecurityEntropySources}, + "structured_config": {"type": StructuredConfig}, + "raw_eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + platforms: Platforms + """Subclass of AvdList with `str` items.""" + trident_forwarding_table_partition: str | None + """Only applied when evpn_multicast is true.""" + reload_delay: ReloadDelay + """Subclass of AvdModel.""" + tcam_profile: str | None + lag_hardware_only: bool | None + default_interface_mtu: int | None + """ + Default interface MTU configured on EOS under "interface defaults". + Takes precedence over the root + key "default_interface_mtu". + """ + p2p_uplinks_mtu: int | None + """ + Set MTU on point to point uplink interfaces. + Takes precedence over the root key "p2p_uplinks_mtu". + .uplink_mtu -> platform_settings.p2p_uplinks_mtu -> p2p_uplinks_mtu -> 9214. + """ + feature_support: FeatureSupport + """Subclass of AvdModel.""" + management_interface: str + """Default value: `"Management1"`""" + security_entropy_sources: SecurityEntropySources + """ + Entropy source improves the randomness of the numbers used to generate MACsec's cryptographic keys. + Subclass of AvdModel. + """ + structured_config: StructuredConfig + """ + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the root level of the final EOS configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + platforms: Platforms | UndefinedType = Undefined, + trident_forwarding_table_partition: str | None | UndefinedType = Undefined, + reload_delay: ReloadDelay | UndefinedType = Undefined, + tcam_profile: str | None | UndefinedType = Undefined, + lag_hardware_only: bool | None | UndefinedType = Undefined, + default_interface_mtu: int | None | UndefinedType = Undefined, + p2p_uplinks_mtu: int | None | UndefinedType = Undefined, + feature_support: FeatureSupport | UndefinedType = Undefined, + management_interface: str | UndefinedType = Undefined, + security_entropy_sources: SecurityEntropySources | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PlatformSettingsItem. + + + Subclass of AvdModel. + + Args: + platforms: Subclass of AvdList with `str` items. + trident_forwarding_table_partition: Only applied when evpn_multicast is true. + reload_delay: Subclass of AvdModel. + tcam_profile: tcam_profile + lag_hardware_only: lag_hardware_only + default_interface_mtu: + Default interface MTU configured on EOS under "interface defaults". + Takes precedence over the root + key "default_interface_mtu". + p2p_uplinks_mtu: + Set MTU on point to point uplink interfaces. + Takes precedence over the root key "p2p_uplinks_mtu". + .uplink_mtu -> platform_settings.p2p_uplinks_mtu -> p2p_uplinks_mtu -> 9214. + feature_support: Subclass of AvdModel. + management_interface: management_interface + security_entropy_sources: + Entropy source improves the randomness of the numbers used to generate MACsec's cryptographic keys. + Subclass of AvdModel. + structured_config: + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the root level of the final EOS configuration. + _custom_data: _custom_data + + """ + + class PlatformSettings(AvdList[PlatformSettingsItem]): + """Subclass of AvdList with `PlatformSettingsItem` items.""" + + PlatformSettings._item_type = PlatformSettingsItem + + class PlatformSpeedGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class SpeedsItem(AvdModel): + """Subclass of AvdModel.""" + + class SpeedGroups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + SpeedGroups._item_type = str + + _fields: ClassVar[dict] = {"speed": {"type": str}, "speed_groups": {"type": SpeedGroups}, "_custom_data": {"type": dict}} + speed: str + speed_groups: SpeedGroups + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + speed: str | UndefinedType = Undefined, + speed_groups: SpeedGroups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SpeedsItem. + + + Subclass of AvdModel. + + Args: + speed: speed + speed_groups: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class Speeds(AvdIndexedList[str, SpeedsItem]): + """Subclass of AvdIndexedList with `SpeedsItem` items. Primary key is `speed` (`str`).""" + + _primary_key: ClassVar[str] = "speed" + + Speeds._item_type = SpeedsItem + + _fields: ClassVar[dict] = {"platform": {"type": str}, "speeds": {"type": Speeds}, "_custom_data": {"type": dict}} + platform: str + speeds: Speeds + """Subclass of AvdIndexedList with `SpeedsItem` items. Primary key is `speed` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + platform: str | UndefinedType = Undefined, + speeds: Speeds | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PlatformSpeedGroupsItem. + + + Subclass of AvdModel. + + Args: + platform: platform + speeds: Subclass of AvdIndexedList with `SpeedsItem` items. Primary key is `speed` (`str`). + _custom_data: _custom_data + + """ + + class PlatformSpeedGroups(AvdIndexedList[str, PlatformSpeedGroupsItem]): + """Subclass of AvdIndexedList with `PlatformSpeedGroupsItem` items. Primary key is `platform` (`str`).""" + + _primary_key: ClassVar[str] = "platform" + + PlatformSpeedGroups._item_type = PlatformSpeedGroupsItem + + class PortProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class TrunkGroups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + TrunkGroups._item_type = str + + class Flowcontrol(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"received": {"type": str}, "_custom_data": {"type": dict}} + received: Literal["received", "send", "on"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + received: Literal["received", "send", "on"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Flowcontrol. + + + Subclass of AvdModel. + + Args: + received: received + _custom_data: _custom_data + + """ + + class Ptp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "endpoint_role": {"type": str, "default": "follower"}, + "profile": {"type": str, "default": "aes67-r16-2016"}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + endpoint_role: Literal["bmca", "default", "follower"] + """Default value: `"follower"`""" + profile: str + """ + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + + Default value: `"aes67-r16-2016"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + endpoint_role: Literal["bmca", "default", "follower"] | UndefinedType = Undefined, + profile: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ptp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + endpoint_role: endpoint_role + profile: + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + _custom_data: _custom_data + + """ + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class LinkTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """ + Tracking group name. + The default group name is taken from fabric variable of the switch, + `link_tracking.groups[0].name` with default value being "LT_GROUP1". + Optional if default + link_tracking settings are configured on the node. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: + Tracking group name. + The default group name is taken from fabric variable of the switch, + `link_tracking.groups[0].name` with default value being "LT_GROUP1". + Optional if default + link_tracking settings are configured on the node. + _custom_data: _custom_data + + """ + + class Dot1x(EosCliConfigGen.EthernetInterfacesItem.Dot1x): + """Subclass of AvdModel.""" + + class Poe(EosCliConfigGen.EthernetInterfacesItem.Poe): + """Subclass of AvdModel.""" + + class StormControl(AvdModel): + """Subclass of AvdModel.""" + + class All(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional variable and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + All. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional variable and is hardware dependent. + _custom_data: _custom_data + + """ + + class Broadcast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional variable and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Broadcast. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional variable and is hardware dependent. + _custom_data: _custom_data + + """ + + class Multicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional variable and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Multicast. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional variable and is hardware dependent. + _custom_data: _custom_data + + """ + + class UnknownUnicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional variable and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + UnknownUnicast. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional variable and is hardware dependent. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "all": {"type": All}, + "broadcast": {"type": Broadcast}, + "multicast": {"type": Multicast}, + "unknown_unicast": {"type": UnknownUnicast}, + "_custom_data": {"type": dict}, + } + all: All + """Subclass of AvdModel.""" + broadcast: Broadcast + """Subclass of AvdModel.""" + multicast: Multicast + """Subclass of AvdModel.""" + unknown_unicast: UnknownUnicast + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + all: All | UndefinedType = Undefined, + broadcast: Broadcast | UndefinedType = Undefined, + multicast: Multicast | UndefinedType = Undefined, + unknown_unicast: UnknownUnicast | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StormControl. + + + Subclass of AvdModel. + + Args: + all: Subclass of AvdModel. + broadcast: Subclass of AvdModel. + multicast: Subclass of AvdModel. + unknown_unicast: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MonitorSessionsItem(AvdModel): + """Subclass of AvdModel.""" + + class SourceSettings(AvdModel): + """Subclass of AvdModel.""" + + class AccessGroup(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"type": {"type": str}, "name": {"type": str}, "priority": {"type": int}, "_custom_data": {"type": dict}} + type: Literal["ip", "ipv6", "mac"] | None + name: str | None + """ACL name.""" + priority: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + type: Literal["ip", "ipv6", "mac"] | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AccessGroup. + + + Subclass of AvdModel. + + Args: + type: type + name: ACL name. + priority: priority + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"direction": {"type": str}, "access_group": {"type": AccessGroup}, "_custom_data": {"type": dict}} + direction: Literal["rx", "tx", "both"] | None + access_group: AccessGroup + """ + This can only be set when `session_settings.access_group` is not set. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction: Literal["rx", "tx", "both"] | None | UndefinedType = Undefined, + access_group: AccessGroup | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SourceSettings. + + + Subclass of AvdModel. + + Args: + direction: direction + access_group: + This can only be set when `session_settings.access_group` is not set. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class SessionSettings(AvdModel): + """Subclass of AvdModel.""" + + class AccessGroup(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"type": {"type": str}, "name": {"type": str}, "_custom_data": {"type": dict}} + type: Literal["ip", "ipv6", "mac"] | None + name: str | None + """ACL name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + type: Literal["ip", "ipv6", "mac"] | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AccessGroup. + + + Subclass of AvdModel. + + Args: + type: type + name: ACL name. + _custom_data: _custom_data + + """ + + class Truncate(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "size": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool | None + size: int | None + """Size in bytes.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + size: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Truncate. + + + Subclass of AvdModel. + + Args: + enabled: enabled + size: Size in bytes. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "encapsulation_gre_metadata_tx": {"type": bool}, + "header_remove_size": {"type": int}, + "access_group": {"type": AccessGroup}, + "rate_limit_per_ingress_chip": {"type": str}, + "rate_limit_per_egress_chip": {"type": str}, + "sample": {"type": int}, + "truncate": {"type": Truncate}, + "_custom_data": {"type": dict}, + } + encapsulation_gre_metadata_tx: bool | None + header_remove_size: int | None + """Number of bytes to remove from header.""" + access_group: AccessGroup + """Subclass of AvdModel.""" + rate_limit_per_ingress_chip: str | None + """ + Ratelimit and unit as string. + Examples: + "100000 bps" + "100 kbps" + "10 mbps" + """ + rate_limit_per_egress_chip: str | None + """ + Ratelimit and unit as string. + Examples: + "100000 bps" + "100 kbps" + "10 mbps" + """ + sample: int | None + truncate: Truncate + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + encapsulation_gre_metadata_tx: bool | None | UndefinedType = Undefined, + header_remove_size: int | None | UndefinedType = Undefined, + access_group: AccessGroup | UndefinedType = Undefined, + rate_limit_per_ingress_chip: str | None | UndefinedType = Undefined, + rate_limit_per_egress_chip: str | None | UndefinedType = Undefined, + sample: int | None | UndefinedType = Undefined, + truncate: Truncate | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SessionSettings. + + + Subclass of AvdModel. + + Args: + encapsulation_gre_metadata_tx: encapsulation_gre_metadata_tx + header_remove_size: Number of bytes to remove from header. + access_group: Subclass of AvdModel. + rate_limit_per_ingress_chip: + Ratelimit and unit as string. + Examples: # fmt: skip + "100000 bps" + "100 kbps" + "10 mbps" + rate_limit_per_egress_chip: + Ratelimit and unit as string. + Examples: # fmt: skip + "100000 bps" + "100 kbps" + "10 mbps" + sample: sample + truncate: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "role": {"type": str}, + "source_settings": {"type": SourceSettings}, + "session_settings": {"type": SessionSettings}, + "_custom_data": {"type": dict}, + } + name: str + """Session name.""" + role: Literal["source", "destination"] | None + source_settings: SourceSettings + """Subclass of AvdModel.""" + session_settings: SessionSettings + """ + Session settings are defined per session name. + Different session_settings for the same session name + will be combined/merged. + + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + role: Literal["source", "destination"] | None | UndefinedType = Undefined, + source_settings: SourceSettings | UndefinedType = Undefined, + session_settings: SessionSettings | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MonitorSessionsItem. + + + Subclass of AvdModel. + + Args: + name: Session name. + role: role + source_settings: Subclass of AvdModel. + session_settings: + Session settings are defined per session name. + Different session_settings for the same session name + will be combined/merged. + + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MonitorSessions(AvdList[MonitorSessionsItem]): + """Subclass of AvdList with `MonitorSessionsItem` items.""" + + MonitorSessions._item_type = MonitorSessionsItem + + class EthernetSegment(AvdModel): + """Subclass of AvdModel.""" + + class DesignatedForwarderPreferences(AvdList[int]): + """Subclass of AvdList with `int` items.""" + + DesignatedForwarderPreferences._item_type = int + + _fields: ClassVar[dict] = { + "short_esi": {"type": str}, + "redundancy": {"type": str}, + "designated_forwarder_algorithm": {"type": str}, + "designated_forwarder_preferences": {"type": DesignatedForwarderPreferences}, + "dont_preempt": {"type": bool}, + "_custom_data": {"type": dict}, + } + short_esi: str + """ + In format xxxx:xxxx:xxxx or "auto". + Define a manual short-esi (be careful using this on profiles) or + set the value to "auto" to automatically generate the value. + Please see the notes under "EVPN A/A + ESI dual and single-attached endpoint scenarios" before setting `short_esi: auto`. + """ + redundancy: Literal["all-active", "single-active"] | None + """ + If omitted, Port-Channels use the EOS default of all-active. + If omitted, Ethernet interfaces are + configured as single-active. + """ + designated_forwarder_algorithm: Literal["auto", "modulus", "preference"] | None + """ + Configure DF algorithm and preferences. + - auto: Use preference-based algorithm and assign preference + based on position of device in the 'switches' list, + e.g., assuming a list of three switches, this + would assign a preference of 200 to the first switch, 100 to the 2nd, and 0 to the third. + - + preference: Set preference for each switch manually using designated_forwarder_preferences key. + - + modulus: Use the default modulus-based algorithm. + If omitted, Port-Channels use the EOS default of + modulus. + If omitted, Ethernet interfaces default to the 'auto' mechanism detailed above. + """ + designated_forwarder_preferences: DesignatedForwarderPreferences + """ + Manual preference as described above, required only for preference algorithm. + + Subclass of AvdList + with `int` items. + """ + dont_preempt: bool | None + """Disable preemption for single-active forwarding when auto/manual DF preference is configured.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + short_esi: str | UndefinedType = Undefined, + redundancy: Literal["all-active", "single-active"] | None | UndefinedType = Undefined, + designated_forwarder_algorithm: Literal["auto", "modulus", "preference"] | None | UndefinedType = Undefined, + designated_forwarder_preferences: DesignatedForwarderPreferences | UndefinedType = Undefined, + dont_preempt: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EthernetSegment. + + + Subclass of AvdModel. + + Args: + short_esi: + In format xxxx:xxxx:xxxx or "auto". + Define a manual short-esi (be careful using this on profiles) or + set the value to "auto" to automatically generate the value. + Please see the notes under "EVPN A/A + ESI dual and single-attached endpoint scenarios" before setting `short_esi: auto`. + redundancy: + If omitted, Port-Channels use the EOS default of all-active. + If omitted, Ethernet interfaces are + configured as single-active. + designated_forwarder_algorithm: + Configure DF algorithm and preferences. + - auto: Use preference-based algorithm and assign preference + based on position of device in the 'switches' list, + e.g., assuming a list of three switches, this + would assign a preference of 200 to the first switch, 100 to the 2nd, and 0 to the third. + - + preference: Set preference for each switch manually using designated_forwarder_preferences key. + - + modulus: Use the default modulus-based algorithm. + If omitted, Port-Channels use the EOS default of + modulus. + If omitted, Ethernet interfaces default to the 'auto' mechanism detailed above. + designated_forwarder_preferences: + Manual preference as described above, required only for preference algorithm. + + Subclass of AvdList + with `int` items. + dont_preempt: Disable preemption for single-active forwarding when auto/manual DF preference is configured. + _custom_data: _custom_data + + """ + + class PortChannel(AvdModel): + """Subclass of AvdModel.""" + + class LacpFallback(AvdModel): + """Subclass of AvdModel.""" + + class Individual(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "_custom_data": {"type": dict}} + profile: str | None + """Port-profile name to inherit configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, profile: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Individual. + + + Subclass of AvdModel. + + Args: + profile: Port-profile name to inherit configuration. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"mode": {"type": str}, "individual": {"type": Individual}, "timeout": {"type": int}, "_custom_data": {"type": dict}} + mode: Literal["static", "individual"] | None + """ + Either static or individual mode is supported. + If the mode is set to "individual" the + "individual.profile" setting must be defined. + """ + individual: Individual + """ + Define parameters for port-channel member interfaces. Applies only if LACP fallback is set to + "individual". + + Subclass of AvdModel. + """ + timeout: int | None + """Timeout in seconds. EOS default is 90 seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["static", "individual"] | None | UndefinedType = Undefined, + individual: Individual | UndefinedType = Undefined, + timeout: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LacpFallback. + + + Subclass of AvdModel. + + Args: + mode: + Either static or individual mode is supported. + If the mode is set to "individual" the + "individual.profile" setting must be defined. + individual: + Define parameters for port-channel member interfaces. Applies only if LACP fallback is set to + "individual". + + Subclass of AvdModel. + timeout: Timeout in seconds. EOS default is 90 seconds. + _custom_data: _custom_data + + """ + + class LacpTimer(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"mode": {"type": str}, "multiplier": {"type": int}, "_custom_data": {"type": dict}} + mode: Literal["normal", "fast"] | None + """LACP mode for interface members.""" + multiplier: int | None + """Number of LACP BPDUs lost before deeming the peer down. EOS default is 3.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["normal", "fast"] | None | UndefinedType = Undefined, + multiplier: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LacpTimer. + + + Subclass of AvdModel. + + Args: + mode: LACP mode for interface members. + multiplier: Number of LACP BPDUs lost before deeming the peer down. EOS default is 3. + _custom_data: _custom_data + + """ + + class SubinterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class EncapsulationVlan(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"client_dot1q": {"type": int}, "_custom_data": {"type": dict}} + client_dot1q: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, client_dot1q: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + EncapsulationVlan. + + + Subclass of AvdModel. + + Args: + client_dot1q: client_dot1q + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "number": {"type": int}, + "short_esi": {"type": str}, + "vlan_id": {"type": int}, + "encapsulation_vlan": {"type": EncapsulationVlan}, + "_custom_data": {"type": dict}, + } + number: int | None + """Subinterface number.""" + short_esi: str | None + """ + In format xxxx:xxxx:xxxx or "auto". + Required for multihomed port-channels with subinterfaces. + """ + vlan_id: int | None + """ + VLAN ID to bridge. + Default is subinterface number. + """ + encapsulation_vlan: EncapsulationVlan + """ + Client VLAN ID encapsulation. + Default is subinterface number. + + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + number: int | None | UndefinedType = Undefined, + short_esi: str | None | UndefinedType = Undefined, + vlan_id: int | None | UndefinedType = Undefined, + encapsulation_vlan: EncapsulationVlan | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SubinterfacesItem. + + + Subclass of AvdModel. + + Args: + number: Subinterface number. + short_esi: + In format xxxx:xxxx:xxxx or "auto". + Required for multihomed port-channels with subinterfaces. + vlan_id: + VLAN ID to bridge. + Default is subinterface number. + encapsulation_vlan: + Client VLAN ID encapsulation. + Default is subinterface number. + + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Subinterfaces(AvdList[SubinterfacesItem]): + """Subclass of AvdList with `SubinterfacesItem` items.""" + + Subinterfaces._item_type = SubinterfacesItem + + class StructuredConfig(EosCliConfigGen.PortChannelInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "mode": {"type": str}, + "channel_id": {"type": int}, + "description": {"type": str}, + "endpoint_port_channel": {"type": str}, + "enabled": {"type": bool, "default": True}, + "ptp_mpass": {"type": bool, "default": False}, + "lacp_fallback": {"type": LacpFallback}, + "lacp_timer": {"type": LacpTimer}, + "subinterfaces": {"type": Subinterfaces}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + mode: Literal["active", "passive", "on"] | None + """Port-Channel Mode.""" + channel_id: int | None + """ + Port-Channel ID. + If no channel_id is specified, an id is generated from the first switch port in the + port channel. + """ + description: str | None + """ + Description or description template to be used on the port-channel interface. + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `endpoint_type` - the `type` from `connected_endpoints_keys` like `server`, `router` etc. + - + `endpoint` - The name of the connected endpoint + - `endpoint_port_channel` - The value from + `endpoint_port_channel` if set. + - `port_channel_id` - The port-channel number for the switch. + - + `adapter_description` - The adapter's description if set. + - `adapter_description_or_endpoint` - + Helper alias of the adapter_description or endpoint. + + The default description is set by + `default_connected_endpoints_port_channel_description`. + By default the description is templated from + the type, name and port_channel interface of the endpoint if set. + """ + endpoint_port_channel: str | None + """ + Name of the port-channel interface on the endpoint. + Used for the port-channel description template + with the field name `peer_interface` + """ + enabled: bool + """ + Port-Channel administrative state. + Setting to false will set port to 'shutdown' in intended + configuration. + + Default value: `True` + """ + ptp_mpass: bool + """ + When MPASS is enabled on an MLAG port-channel, MLAG peers coordinate to function as a single PTP + logical device. + Arista PTP enabled devices always place PTP messages on the same physical link + within the port-channel. + Hence, MPASS is needed only on MLAG port-channels connected to non-Arista + devices. + + Default value: `False` + """ + lacp_fallback: LacpFallback + """ + LACP fallback configuration. + + Subclass of AvdModel. + """ + lacp_timer: LacpTimer + """ + LACP timer configuration. Applies only when Port-channel mode is not "on". + + Subclass of AvdModel. + """ + subinterfaces: Subinterfaces + """ + Port-Channel L2 Subinterfaces + Subinterfaces are only supported on routed port-channels, which means + they cannot be configured on MLAG port-channels. + Setting short_esi: auto generates the short_esi + automatically using a hash of configuration elements. + Please see the notes under "EVPN A/A ESI dual- + attached endpoint scenario" before setting short_esi: auto. + + + Subclass of AvdList with + `SubinterfacesItem` items. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the port-channel interface in the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["active", "passive", "on"] | None | UndefinedType = Undefined, + channel_id: int | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + endpoint_port_channel: str | None | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + ptp_mpass: bool | UndefinedType = Undefined, + lacp_fallback: LacpFallback | UndefinedType = Undefined, + lacp_timer: LacpTimer | UndefinedType = Undefined, + subinterfaces: Subinterfaces | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PortChannel. + + + Subclass of AvdModel. + + Args: + mode: Port-Channel Mode. + channel_id: + Port-Channel ID. + If no channel_id is specified, an id is generated from the first switch port in the + port channel. + description: + Description or description template to be used on the port-channel interface. + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `endpoint_type` - the `type` from `connected_endpoints_keys` like `server`, `router` etc. + - + `endpoint` - The name of the connected endpoint + - `endpoint_port_channel` - The value from + `endpoint_port_channel` if set. + - `port_channel_id` - The port-channel number for the switch. + - + `adapter_description` - The adapter's description if set. + - `adapter_description_or_endpoint` - + Helper alias of the adapter_description or endpoint. + + The default description is set by + `default_connected_endpoints_port_channel_description`. + By default the description is templated from + the type, name and port_channel interface of the endpoint if set. + endpoint_port_channel: + Name of the port-channel interface on the endpoint. + Used for the port-channel description template + with the field name `peer_interface` + enabled: + Port-Channel administrative state. + Setting to false will set port to 'shutdown' in intended + configuration. + ptp_mpass: + When MPASS is enabled on an MLAG port-channel, MLAG peers coordinate to function as a single PTP + logical device. + Arista PTP enabled devices always place PTP messages on the same physical link + within the port-channel. + Hence, MPASS is needed only on MLAG port-channels connected to non-Arista + devices. + lacp_fallback: + LACP fallback configuration. + + Subclass of AvdModel. + lacp_timer: + LACP timer configuration. Applies only when Port-channel mode is not "on". + + Subclass of AvdModel. + subinterfaces: + Port-Channel L2 Subinterfaces + Subinterfaces are only supported on routed port-channels, which means + they cannot be configured on MLAG port-channels. + Setting short_esi: auto generates the short_esi + automatically using a hash of configuration elements. + Please see the notes under "EVPN A/A ESI dual- + attached endpoint scenario" before setting short_esi: auto. + + + Subclass of AvdList with + `SubinterfacesItem` items. + raw_eos_cli: EOS CLI rendered directly on the port-channel interface in the final EOS configuration. + structured_config: + Custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "profile": {"type": str}, + "parent_profile": {"type": str}, + "speed": {"type": str}, + "description": {"type": str}, + "enabled": {"type": bool, "default": True}, + "mode": {"type": str}, + "mtu": {"type": int}, + "l2_mtu": {"type": int}, + "l2_mru": {"type": int}, + "native_vlan": {"type": int}, + "native_vlan_tag": {"type": bool}, + "phone_vlan": {"type": int}, + "phone_trunk_mode": {"type": str}, + "trunk_groups": {"type": TrunkGroups}, + "vlans": {"type": str}, + "spanning_tree_portfast": {"type": str}, + "spanning_tree_bpdufilter": {"type": str}, + "spanning_tree_bpduguard": {"type": str}, + "flowcontrol": {"type": Flowcontrol}, + "qos_profile": {"type": str}, + "ptp": {"type": Ptp}, + "sflow": {"type": bool}, + "flow_tracking": {"type": FlowTracking}, + "link_tracking": {"type": LinkTracking}, + "dot1x": {"type": Dot1x}, + "poe": {"type": Poe}, + "storm_control": {"type": StormControl}, + "monitor_sessions": {"type": MonitorSessions}, + "ethernet_segment": {"type": EthernetSegment}, + "port_channel": {"type": PortChannel}, + "validate_state": {"type": bool}, + "validate_lldp": {"type": bool}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + profile: str + """Port profile name.""" + parent_profile: str | None + """ + Parent profile is optional. + Port_profiles can refer to another port_profile to inherit settings in + up to two levels (adapter->profile->parent_profile). + """ + speed: str | None + """ + Set adapter speed in the format `` or `forced ` or `auto + `. + If not specified speed will be auto. + """ + description: str | None + """ + Description or description template to be used on all ports. + This can be a template using the AVD + string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom- + descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - + `endpoint_type` - the `type` from `connected_endpoints_keys` like `server`, `router` etc. + - + `endpoint` - The name of the connected endpoint + - `endpoint_port` - The value from + `endpoint_ports` for this switch port if set. + + The default description is set by + `default_connected_endpoints_description`. + By default the description is templated from the type, + name and port of the endpoint if set. + """ + enabled: bool + """ + Administrative state, setting to false will set the port to 'shutdown' in the intended + configuration. + + Default value: `True` + """ + mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None + """Interface mode.""" + mtu: int | None + l2_mtu: int | None + """"l2_mtu" should only be defined for platforms supporting the "l2 mtu" CLI.""" + l2_mru: int | None + """"l2_mru" should only be defined for platforms supporting the "l2 mru" CLI.""" + native_vlan: int | None + """ + Native VLAN for a trunk port. + If both `native_vlan` and `native_vlan_tag` are set, `native_vlan_tag` + takes precedence. + """ + native_vlan_tag: bool | None + """If both `native_vlan` and `native_vlan_tag` are set, `native_vlan_tag` takes precedence.""" + phone_vlan: int | None + """ + Phone VLAN for a mode `trunk phone` port. + Requires `mode: trunk phone` to be set. + """ + phone_trunk_mode: Literal["tagged", "untagged", "tagged phone", "untagged phone"] | None + """ + Specify if the phone traffic is tagged or untagged. + If both data and phone traffic are untagged, + MAC-Based VLAN Assignment (MBVA) is used, if supported by the model of switch. + """ + trunk_groups: TrunkGroups + """ + Required with `enable_trunk_groups: true`. + Trunk Groups are used for limiting VLANs on trunk ports + to VLANs with the same Trunk Group. + + + Subclass of AvdList with `str` items. + """ + vlans: str | None + """ + Interface VLANs - if not set, the EOS default is that all VLANs are allowed for trunk ports, and + VLAN 1 will be used for access ports. + """ + spanning_tree_portfast: Literal["edge", "network"] | None + spanning_tree_bpdufilter: Literal["enabled", "disabled", "True", "False", "true", "false"] | None + spanning_tree_bpduguard: Literal["enabled", "disabled", "True", "False", "true", "false"] | None + flowcontrol: Flowcontrol + """Subclass of AvdModel.""" + qos_profile: str | None + """QOS profile name.""" + ptp: Ptp + """ + The global PTP profile parameters will be applied to all connected endpoints where `ptp` is manually + enabled. + `ptp role master` is set to ensure control over the PTP topology. + + + Subclass of AvdModel. + """ + sflow: bool | None + """Configures sFlow on the interface. Overrides `fabric_sflow.endpoints` setting.""" + flow_tracking: FlowTracking + """ + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.endpoints` setting. + Subclass of AvdModel. + """ + link_tracking: LinkTracking + """ + Configure the downstream interfaces of a respective Link Tracking Group. + If `port_channel` is + defined in an adapter, then the port-channel interface is configured to be the downstream. + Else all + the ethernet interfaces will be configured as downstream -> to configure single-active EVPN + multihomed networks. + + + Subclass of AvdModel. + """ + dot1x: Dot1x + """ + 802.1x + + Subclass of AvdModel. + """ + poe: Poe + """ + Power Over Ethernet settings applied on port. Only configured if platform supports PoE. + + Subclass of + AvdModel. + """ + storm_control: StormControl + """ + Storm control settings applied on port toward the endpoint. + + Subclass of AvdModel. + """ + monitor_sessions: MonitorSessions + """ + Used to define switchports as source or destination for monitoring sessions. + + Subclass of AvdList + with `MonitorSessionsItem` items. + """ + ethernet_segment: EthernetSegment + """ + Settings for all or single-active EVPN multihoming. + + Subclass of AvdModel. + """ + port_channel: PortChannel + """ + Used for port-channel adapter. + + Subclass of AvdModel. + """ + validate_state: bool | None + """ + Set to false to disable interface state and LLDP topology validation performed by the + `eos_validate_state` role. + """ + validate_lldp: bool | None + """Set to false to disable the LLDP topology validation performed by the `eos_validate_state` role.""" + raw_eos_cli: str | None + """EOS CLI rendered directly on the ethernet interface in the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config added under ethernet_interfaces.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + parent_profile: str | None | UndefinedType = Undefined, + speed: str | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + l2_mtu: int | None | UndefinedType = Undefined, + l2_mru: int | None | UndefinedType = Undefined, + native_vlan: int | None | UndefinedType = Undefined, + native_vlan_tag: bool | None | UndefinedType = Undefined, + phone_vlan: int | None | UndefinedType = Undefined, + phone_trunk_mode: Literal["tagged", "untagged", "tagged phone", "untagged phone"] | None | UndefinedType = Undefined, + trunk_groups: TrunkGroups | UndefinedType = Undefined, + vlans: str | None | UndefinedType = Undefined, + spanning_tree_portfast: Literal["edge", "network"] | None | UndefinedType = Undefined, + spanning_tree_bpdufilter: Literal["enabled", "disabled", "True", "False", "true", "false"] | None | UndefinedType = Undefined, + spanning_tree_bpduguard: Literal["enabled", "disabled", "True", "False", "true", "false"] | None | UndefinedType = Undefined, + flowcontrol: Flowcontrol | UndefinedType = Undefined, + qos_profile: str | None | UndefinedType = Undefined, + ptp: Ptp | UndefinedType = Undefined, + sflow: bool | None | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + link_tracking: LinkTracking | UndefinedType = Undefined, + dot1x: Dot1x | UndefinedType = Undefined, + poe: Poe | UndefinedType = Undefined, + storm_control: StormControl | UndefinedType = Undefined, + monitor_sessions: MonitorSessions | UndefinedType = Undefined, + ethernet_segment: EthernetSegment | UndefinedType = Undefined, + port_channel: PortChannel | UndefinedType = Undefined, + validate_state: bool | None | UndefinedType = Undefined, + validate_lldp: bool | None | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PortProfilesItem. + + + Subclass of AvdModel. + + Args: + profile: Port profile name. + parent_profile: + Parent profile is optional. + Port_profiles can refer to another port_profile to inherit settings in + up to two levels (adapter->profile->parent_profile). + speed: + Set adapter speed in the format `` or `forced ` or `auto + `. + If not specified speed will be auto. + description: + Description or description template to be used on all ports. + This can be a template using the AVD + string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom- + descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - + `endpoint_type` - the `type` from `connected_endpoints_keys` like `server`, `router` etc. + - + `endpoint` - The name of the connected endpoint + - `endpoint_port` - The value from + `endpoint_ports` for this switch port if set. + + The default description is set by + `default_connected_endpoints_description`. + By default the description is templated from the type, + name and port of the endpoint if set. + enabled: + Administrative state, setting to false will set the port to 'shutdown' in the intended + configuration. + mode: Interface mode. + mtu: mtu + l2_mtu: "l2_mtu" should only be defined for platforms supporting the "l2 mtu" CLI. + l2_mru: "l2_mru" should only be defined for platforms supporting the "l2 mru" CLI. + native_vlan: + Native VLAN for a trunk port. + If both `native_vlan` and `native_vlan_tag` are set, `native_vlan_tag` + takes precedence. + native_vlan_tag: If both `native_vlan` and `native_vlan_tag` are set, `native_vlan_tag` takes precedence. + phone_vlan: + Phone VLAN for a mode `trunk phone` port. + Requires `mode: trunk phone` to be set. + phone_trunk_mode: + Specify if the phone traffic is tagged or untagged. + If both data and phone traffic are untagged, + MAC-Based VLAN Assignment (MBVA) is used, if supported by the model of switch. + trunk_groups: + Required with `enable_trunk_groups: true`. + Trunk Groups are used for limiting VLANs on trunk ports + to VLANs with the same Trunk Group. + + + Subclass of AvdList with `str` items. + vlans: + Interface VLANs - if not set, the EOS default is that all VLANs are allowed for trunk ports, and + VLAN 1 will be used for access ports. + spanning_tree_portfast: spanning_tree_portfast + spanning_tree_bpdufilter: spanning_tree_bpdufilter + spanning_tree_bpduguard: spanning_tree_bpduguard + flowcontrol: Subclass of AvdModel. + qos_profile: QOS profile name. + ptp: + The global PTP profile parameters will be applied to all connected endpoints where `ptp` is manually + enabled. + `ptp role master` is set to ensure control over the PTP topology. + + + Subclass of AvdModel. + sflow: Configures sFlow on the interface. Overrides `fabric_sflow.endpoints` setting. + flow_tracking: + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.endpoints` setting. + Subclass of AvdModel. + link_tracking: + Configure the downstream interfaces of a respective Link Tracking Group. + If `port_channel` is + defined in an adapter, then the port-channel interface is configured to be the downstream. + Else all + the ethernet interfaces will be configured as downstream -> to configure single-active EVPN + multihomed networks. + + + Subclass of AvdModel. + dot1x: + 802.1x + + Subclass of AvdModel. + poe: + Power Over Ethernet settings applied on port. Only configured if platform supports PoE. + + Subclass of + AvdModel. + storm_control: + Storm control settings applied on port toward the endpoint. + + Subclass of AvdModel. + monitor_sessions: + Used to define switchports as source or destination for monitoring sessions. + + Subclass of AvdList + with `MonitorSessionsItem` items. + ethernet_segment: + Settings for all or single-active EVPN multihoming. + + Subclass of AvdModel. + port_channel: + Used for port-channel adapter. + + Subclass of AvdModel. + validate_state: + Set to false to disable interface state and LLDP topology validation performed by the + `eos_validate_state` role. + validate_lldp: Set to false to disable the LLDP topology validation performed by the `eos_validate_state` role. + raw_eos_cli: EOS CLI rendered directly on the ethernet interface in the final EOS configuration. + structured_config: + Custom structured config added under ethernet_interfaces.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PortProfiles(AvdIndexedList[str, PortProfilesItem]): + """Subclass of AvdIndexedList with `PortProfilesItem` items. Primary key is `profile` (`str`).""" + + _primary_key: ClassVar[str] = "profile" + + PortProfiles._item_type = PortProfilesItem + + class PtpProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class Announce(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interval": {"type": int}, "timeout": {"type": int}, "_custom_data": {"type": dict}} + interval: int | None + timeout: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | None | UndefinedType = Undefined, + timeout: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Announce. + + + Subclass of AvdModel. + + Args: + interval: interval + timeout: timeout + _custom_data: _custom_data + + """ + + class SyncMessage(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interval": {"type": int}, "_custom_data": {"type": dict}} + interval: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, interval: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + SyncMessage. + + + Subclass of AvdModel. + + Args: + interval: interval + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "profile": {"type": str}, + "announce": {"type": Announce}, + "delay_req": {"type": int}, + "sync_message": {"type": SyncMessage}, + "transport": {"type": str}, + "_custom_data": {"type": dict}, + } + profile: str + """PTP profile.""" + announce: Announce + """ + PTP announce interval. + + Subclass of AvdModel. + """ + delay_req: int | None + sync_message: SyncMessage + """ + PTP sync message interval. + + Subclass of AvdModel. + """ + transport: Literal["ipv4"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + announce: Announce | UndefinedType = Undefined, + delay_req: int | None | UndefinedType = Undefined, + sync_message: SyncMessage | UndefinedType = Undefined, + transport: Literal["ipv4"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PtpProfilesItem. + + + Subclass of AvdModel. + + Args: + profile: PTP profile. + announce: + PTP announce interval. + + Subclass of AvdModel. + delay_req: delay_req + sync_message: + PTP sync message interval. + + Subclass of AvdModel. + transport: transport + _custom_data: _custom_data + + """ + + class PtpProfiles(AvdIndexedList[str, PtpProfilesItem]): + """Subclass of AvdIndexedList with `PtpProfilesItem` items. Primary key is `profile` (`str`).""" + + _primary_key: ClassVar[str] = "profile" + + PtpProfiles._item_type = PtpProfilesItem + + class PtpSettings(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "profile": {"type": str, "default": "aes67-r16-2016"}, + "domain": {"type": int, "default": 127}, + "auto_clock_identity": {"type": bool, "default": True}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + profile: str + """ + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + + Default value: `"aes67-r16-2016"` + """ + domain: int + """Default value: `127`""" + auto_clock_identity: bool + """Default value: `True`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + profile: str | UndefinedType = Undefined, + domain: int | UndefinedType = Undefined, + auto_clock_identity: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PtpSettings. + + + Subclass of AvdModel. + + Args: + enabled: enabled + profile: + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + domain: domain + auto_clock_identity: auto_clock_identity + _custom_data: _custom_data + + """ + + class QueueMonitorLength(AvdModel): + """Subclass of AvdModel.""" + + class DefaultThresholds(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"high": {"type": int}, "low": {"type": int}, "_custom_data": {"type": dict}} + high: int + """Default high threshold for Ethernet Interfaces.""" + low: int | None + """ + Default low threshold for Ethernet Interfaces. + Low threshold support is platform dependent. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + high: int | UndefinedType = Undefined, + low: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultThresholds. + + + Subclass of AvdModel. + + Args: + high: Default high threshold for Ethernet Interfaces. + low: + Default low threshold for Ethernet Interfaces. + Low threshold support is platform dependent. + _custom_data: _custom_data + + """ + + class Cpu(AvdModel): + """Subclass of AvdModel.""" + + class Thresholds(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"high": {"type": int}, "low": {"type": int}, "_custom_data": {"type": dict}} + high: int + low: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + high: int | UndefinedType = Undefined, + low: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Thresholds. + + + Subclass of AvdModel. + + Args: + high: high + low: low + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"thresholds": {"type": Thresholds}, "_custom_data": {"type": dict}} + thresholds: Thresholds + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, thresholds: Thresholds | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Cpu. + + + Subclass of AvdModel. + + Args: + thresholds: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "notifying": {"type": bool}, + "default_thresholds": {"type": DefaultThresholds}, + "log": {"type": int}, + "cpu": {"type": Cpu}, + "tx_latency": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool + notifying: bool | None + """ + If True, `eos_designs` will configure `queue-monitor length notifying` according to the + `platform_settings.[].feature_support.queue_monitor_length_notify` setting. + """ + default_thresholds: DefaultThresholds + """Subclass of AvdModel.""" + log: int | None + """Logging interval in seconds.""" + cpu: Cpu + """Subclass of AvdModel.""" + tx_latency: bool | None + """Enable tx-latency mode.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + notifying: bool | None | UndefinedType = Undefined, + default_thresholds: DefaultThresholds | UndefinedType = Undefined, + log: int | None | UndefinedType = Undefined, + cpu: Cpu | UndefinedType = Undefined, + tx_latency: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + QueueMonitorLength. + + + Subclass of AvdModel. + + Args: + enabled: enabled + notifying: + If True, `eos_designs` will configure `queue-monitor length notifying` according to the + `platform_settings.[].feature_support.queue_monitor_length_notify` setting. + default_thresholds: Subclass of AvdModel. + log: Logging interval in seconds. + cpu: Subclass of AvdModel. + tx_latency: Enable tx-latency mode. + _custom_data: _custom_data + + """ + + class Redundancy(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"protocol": {"type": str}, "_custom_data": {"type": dict}} + protocol: Literal["sso", "rpr"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, protocol: Literal["sso", "rpr"] | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Redundancy. + + + Subclass of AvdModel. + + Args: + protocol: protocol + _custom_data: _custom_data + + """ + + class SflowSettings(AvdModel): + """Subclass of AvdModel.""" + + class Sample(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"rate": {"type": int}, "_custom_data": {"type": dict}} + rate: int | None + """ + Packet sampling rate that defines the average number of ingress packets that pass through an + interface for every packet that is sampled. + A rate of 16384 corresponds to an average sample of one + per 16384 packets. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, rate: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Sample. + + + Subclass of AvdModel. + + Args: + rate: + Packet sampling rate that defines the average number of ingress packets that pass through an + interface for every packet that is sampled. + A rate of 16384 corresponds to an average sample of one + per 16384 packets. + _custom_data: _custom_data + + """ + + class DestinationsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"destination": {"type": str}, "port": {"type": int}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + destination: str + """sFlow destination name or IP address.""" + port: int | None + """UDP Port number. The default port number for sFlow is 6343.""" + vrf: str | None + """ + If not set, the VRF is automatically picked up from the global setting `default_mgmt_method`. + The + value of `vrf` will be interpreted according to these rules: + - `use_mgmt_interface_vrf` will + configure the sFlow destination under the VRF set with `mgmt_interface_vrf` and set the + `mgmt_interface` as sFlow source-interface. + An error will be raised if `mgmt_ip` or `ipv6_mgmt_ip` + are not configured for the device. + - `use_inband_mgmt_vrf` will configure the sFlow destination + under the VRF set with `inband_mgmt_vrf` and set the `inband_mgmt_interface` as sFlow source- + interface. + An error will be raised if inband management is not configured for the device. + - Any + other string will be used directly as the VRF name. Remember to set the + `sflow_settings.vrfs[].source_interface` if needed. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + destination: str | UndefinedType = Undefined, + port: int | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DestinationsItem. + + + Subclass of AvdModel. + + Args: + destination: sFlow destination name or IP address. + port: UDP Port number. The default port number for sFlow is 6343. + vrf: + If not set, the VRF is automatically picked up from the global setting `default_mgmt_method`. + The + value of `vrf` will be interpreted according to these rules: + - `use_mgmt_interface_vrf` will + configure the sFlow destination under the VRF set with `mgmt_interface_vrf` and set the + `mgmt_interface` as sFlow source-interface. + An error will be raised if `mgmt_ip` or `ipv6_mgmt_ip` + are not configured for the device. + - `use_inband_mgmt_vrf` will configure the sFlow destination + under the VRF set with `inband_mgmt_vrf` and set the `inband_mgmt_interface` as sFlow source- + interface. + An error will be raised if inband management is not configured for the device. + - Any + other string will be used directly as the VRF name. Remember to set the + `sflow_settings.vrfs[].source_interface` if needed. + _custom_data: _custom_data + + """ + + class Destinations(AvdList[DestinationsItem]): + """Subclass of AvdList with `DestinationsItem` items.""" + + Destinations._item_type = DestinationsItem + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "source_interface": {"type": str}, "_custom_data": {"type": dict}} + name: str + """VRF name.""" + source_interface: str | None + """ + Source interface to use for sFlow destinations in this VRF. + If set for the VRFs defined by + `mgmt_interface_vrf` or `inband_mgmt_vrf`, this setting will take precedence. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + source_interface: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: VRF name. + source_interface: + Source interface to use for sFlow destinations in this VRF. + If set for the VRFs defined by + `mgmt_interface_vrf` or `inband_mgmt_vrf`, this setting will take precedence. + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + _fields: ClassVar[dict] = {"sample": {"type": Sample}, "destinations": {"type": Destinations}, "vrfs": {"type": Vrfs}, "_custom_data": {"type": dict}} + sample: Sample + """Subclass of AvdModel.""" + destinations: Destinations + """Subclass of AvdList with `DestinationsItem` items.""" + vrfs: Vrfs + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + sample: Sample | UndefinedType = Undefined, + destinations: Destinations | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SflowSettings. + + + Subclass of AvdModel. + + Args: + sample: Subclass of AvdModel. + destinations: Subclass of AvdList with `DestinationsItem` items. + vrfs: Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class SnmpSettings(AvdModel): + """Subclass of AvdModel.""" + + class Vrfs(EosCliConfigGen.SnmpServer.Vrfs): + pass + + class UsersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "group": {"type": str}, + "version": {"type": str}, + "auth": {"type": str}, + "auth_passphrase": {"type": str}, + "priv": {"type": str}, + "priv_passphrase": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str | None + """Username.""" + group: str | None + """Group name.""" + version: Literal["v1", "v2c", "v3"] | None + auth: Literal["md5", "sha", "sha256", "sha384", "sha512"] | None + auth_passphrase: str | None + """Cleartext passphrase so the recommendation is to use vault. Requires 'auth' to be set.""" + priv: Literal["des", "aes", "aes192", "aes256"] | None + priv_passphrase: str | None + """Cleartext passphrase so the recommendation is to use vault. Requires 'priv' to be set.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + group: str | None | UndefinedType = Undefined, + version: Literal["v1", "v2c", "v3"] | None | UndefinedType = Undefined, + auth: Literal["md5", "sha", "sha256", "sha384", "sha512"] | None | UndefinedType = Undefined, + auth_passphrase: str | None | UndefinedType = Undefined, + priv: Literal["des", "aes", "aes192", "aes256"] | None | UndefinedType = Undefined, + priv_passphrase: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + UsersItem. + + + Subclass of AvdModel. + + Args: + name: Username. + group: Group name. + version: version + auth: auth + auth_passphrase: Cleartext passphrase so the recommendation is to use vault. Requires 'auth' to be set. + priv: priv + priv_passphrase: Cleartext passphrase so the recommendation is to use vault. Requires 'priv' to be set. + _custom_data: _custom_data + + """ + + class Users(AvdList[UsersItem]): + """Subclass of AvdList with `UsersItem` items.""" + + Users._item_type = UsersItem + + class HostsItem(AvdModel): + """Subclass of AvdModel.""" + + class UsersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"username": {"type": str}, "authentication_level": {"type": str}, "_custom_data": {"type": dict}} + username: str | None + authentication_level: Literal["auth", "noauth", "priv"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + username: str | None | UndefinedType = Undefined, + authentication_level: Literal["auth", "noauth", "priv"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + UsersItem. + + + Subclass of AvdModel. + + Args: + username: username + authentication_level: authentication_level + _custom_data: _custom_data + + """ + + class Users(AvdList[UsersItem]): + """Subclass of AvdList with `UsersItem` items.""" + + Users._item_type = UsersItem + + _fields: ClassVar[dict] = { + "host": {"type": str}, + "vrf": {"type": str}, + "use_mgmt_interface_vrf": {"type": bool}, + "use_inband_mgmt_vrf": {"type": bool}, + "version": {"type": str}, + "community": {"type": str}, + "users": {"type": Users}, + "_custom_data": {"type": dict}, + } + host: str | None + """Host IP address or name.""" + vrf: str | None + """ + VRF Name. + Can be used in combination with "use_mgmt_interface_vrf" and "use_inband_mgmt_vrf" to + configure the SNMP host under multiple VRFs. + """ + use_mgmt_interface_vrf: bool | None + """ + Configure the SNMP host under the VRF set with "mgmt_interface_vrf". Ignored if 'mgmt_ip' or + 'ipv6_mgmt_ip' are not configured for the device, so if the host is only configured with this VRF, + the host will not be configured at all. Can be used in combination with "vrf" and + "use_inband_mgmt_vrf" to configure the SNMP host under multiple VRFs. + """ + use_inband_mgmt_vrf: bool | None + """ + Configure the SNMP host under the VRF set with "inband_mgmt_vrf". Ignored if inband management is + not configured for the device, so if the host is only configured with this VRF, the host will not be + configured at all. Can be used in combination with "vrf" and "use_mgmt_interface_vrf" to configure + the SNMP host under multiple VRFs. + """ + version: Literal["1", "2c", "3"] | None + community: str | None + """Community name.""" + users: Users + """Subclass of AvdList with `UsersItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + host: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + use_mgmt_interface_vrf: bool | None | UndefinedType = Undefined, + use_inband_mgmt_vrf: bool | None | UndefinedType = Undefined, + version: Literal["1", "2c", "3"] | None | UndefinedType = Undefined, + community: str | None | UndefinedType = Undefined, + users: Users | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + HostsItem. + + + Subclass of AvdModel. + + Args: + host: Host IP address or name. + vrf: + VRF Name. + Can be used in combination with "use_mgmt_interface_vrf" and "use_inband_mgmt_vrf" to + configure the SNMP host under multiple VRFs. + use_mgmt_interface_vrf: + Configure the SNMP host under the VRF set with "mgmt_interface_vrf". Ignored if 'mgmt_ip' or + 'ipv6_mgmt_ip' are not configured for the device, so if the host is only configured with this VRF, + the host will not be configured at all. Can be used in combination with "vrf" and + "use_inband_mgmt_vrf" to configure the SNMP host under multiple VRFs. + use_inband_mgmt_vrf: + Configure the SNMP host under the VRF set with "inband_mgmt_vrf". Ignored if inband management is + not configured for the device, so if the host is only configured with this VRF, the host will not be + configured at all. Can be used in combination with "vrf" and "use_mgmt_interface_vrf" to configure + the SNMP host under multiple VRFs. + version: version + community: Community name. + users: Subclass of AvdList with `UsersItem` items. + _custom_data: _custom_data + + """ + + class Hosts(AvdList[HostsItem]): + """Subclass of AvdList with `HostsItem` items.""" + + Hosts._item_type = HostsItem + + class Communities(EosCliConfigGen.SnmpServer.Communities): + pass + + class Ipv4AclsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + """IPv4 access list name.""" + vrf: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv4AclsItem. + + + Subclass of AvdModel. + + Args: + name: IPv4 access list name. + vrf: vrf + _custom_data: _custom_data + + """ + + class Ipv4Acls(AvdList[Ipv4AclsItem]): + """Subclass of AvdList with `Ipv4AclsItem` items.""" + + Ipv4Acls._item_type = Ipv4AclsItem + + class Ipv6AclsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "vrf": {"type": str}, "_custom_data": {"type": dict}} + name: str | None + """IPv6 access list name.""" + vrf: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6AclsItem. + + + Subclass of AvdModel. + + Args: + name: IPv6 access list name. + vrf: vrf + _custom_data: _custom_data + + """ + + class Ipv6Acls(AvdList[Ipv6AclsItem]): + """Subclass of AvdList with `Ipv6AclsItem` items.""" + + Ipv6Acls._item_type = Ipv6AclsItem + + class ViewsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "mib_family_name": {"type": str}, "included": {"type": bool}, "_custom_data": {"type": dict}} + name: str | None + """SNMP view name.""" + mib_family_name: str | None + included: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + mib_family_name: str | None | UndefinedType = Undefined, + included: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ViewsItem. + + + Subclass of AvdModel. + + Args: + name: SNMP view name. + mib_family_name: mib_family_name + included: included + _custom_data: _custom_data + + """ + + class Views(AvdList[ViewsItem]): + """Subclass of AvdList with `ViewsItem` items.""" + + Views._item_type = ViewsItem + + class GroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "version": {"type": str}, + "authentication": {"type": str}, + "read": {"type": str}, + "write": {"type": str}, + "notify": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str | None + """Group name.""" + version: Literal["v1", "v2c", "v3"] | None + authentication: Literal["auth", "noauth", "priv"] | None + read: str | None + """Read view.""" + write: str | None + """Write view.""" + notify: str | None + """Notify view.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + version: Literal["v1", "v2c", "v3"] | None | UndefinedType = Undefined, + authentication: Literal["auth", "noauth", "priv"] | None | UndefinedType = Undefined, + read: str | None | UndefinedType = Undefined, + write: str | None | UndefinedType = Undefined, + notify: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GroupsItem. + + + Subclass of AvdModel. + + Args: + name: Group name. + version: version + authentication: authentication + read: Read view. + write: Write view. + notify: Notify view. + _custom_data: _custom_data + + """ + + class Groups(AvdList[GroupsItem]): + """Subclass of AvdList with `GroupsItem` items.""" + + Groups._item_type = GroupsItem + + class Traps(EosCliConfigGen.SnmpServer.Traps): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "contact": {"type": str}, + "location": {"type": bool, "default": False}, + "vrfs": {"type": Vrfs}, + "enable_mgmt_interface_vrf": {"type": bool}, + "enable_inband_mgmt_vrf": {"type": bool}, + "compute_local_engineid": {"type": bool, "default": False}, + "compute_local_engineid_source": {"type": str, "default": "hostname_and_ip"}, + "compute_v3_user_localized_key": {"type": bool, "default": False}, + "users": {"type": Users}, + "hosts": {"type": Hosts}, + "communities": {"type": Communities}, + "ipv4_acls": {"type": Ipv4Acls}, + "ipv6_acls": {"type": Ipv6Acls}, + "views": {"type": Views}, + "groups": {"type": Groups}, + "traps": {"type": Traps}, + "_custom_data": {"type": dict}, + } + contact: str | None + """SNMP contact.""" + location: bool + """ + Set SNMP location. Formatted as " + ". + + Default value: `False` + """ + vrfs: Vrfs + """ + Enable/disable SNMP for one or more VRFs. + Can be used in combination with + "enable_mgmt_interface_vrf" and "enable_inband_mgmt_vrf". + """ + enable_mgmt_interface_vrf: bool | None + """ + Enable/disable SNMP for the VRF set with "mgmt_interface_vrf". + Ignored if 'mgmt_ip' or + 'ipv6_mgmt_ip' are not configured for the device. + Can be used in combination with "vrfs" and + "enable_inband_mgmt_vrf". + """ + enable_inband_mgmt_vrf: bool | None + """ + Enable/disable SNMP for the VRF set with "inband_mgmt_vrf". + Ignored if inband management is not + configured for the device. + Can be used in combination with "vrfs" and "enable_mgmt_interface_vrf". + """ + compute_local_engineid: bool + """ + Generate a local engineId for SNMP using the 'compute_local_engineid_source' method. + + Default value: `False` + """ + compute_local_engineid_source: Literal["hostname_and_ip", "system_mac"] + """ + `compute_local_engineid_source` supports: + - `hostname_and_ip` generate a local engineId for SNMP by + hashing via SHA1 + the string generated via the concatenation of the hostname plus the management + IP. + {{ inventory_hostname }} + {{ switch.mgmt_ip }}. + - `system_mac` generate the switch default + engine id for AVD usage. + To use this, `system_mac_address` MUST be set for the device. + The + formula is f5717f + system_mac_address + 00. + + Default value: `"hostname_and_ip"` + """ + compute_v3_user_localized_key: bool + """ + Requires compute_local_engineid to be `true`. + If enabled, the SNMPv3 passphrases for auth and priv + are transformed using RFC 2574, matching the value they would take in EOS CLI. + The algorithm + requires a local engineId, which is unknown to AVD, hence the necessity to generate one beforehand. + + Default value: `False` + """ + users: Users + """ + Configuration of local SNMP users. + Configuration of remote SNMP users are currently only possible + using `structured_config`. + + Subclass of AvdList with `UsersItem` items. + """ + hosts: Hosts + """Subclass of AvdList with `HostsItem` items.""" + communities: Communities + ipv4_acls: Ipv4Acls + """Subclass of AvdList with `Ipv4AclsItem` items.""" + ipv6_acls: Ipv6Acls + """Subclass of AvdList with `Ipv6AclsItem` items.""" + views: Views + """Subclass of AvdList with `ViewsItem` items.""" + groups: Groups + """Subclass of AvdList with `GroupsItem` items.""" + traps: Traps + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + contact: str | None | UndefinedType = Undefined, + location: bool | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + enable_mgmt_interface_vrf: bool | None | UndefinedType = Undefined, + enable_inband_mgmt_vrf: bool | None | UndefinedType = Undefined, + compute_local_engineid: bool | UndefinedType = Undefined, + compute_local_engineid_source: Literal["hostname_and_ip", "system_mac"] | UndefinedType = Undefined, + compute_v3_user_localized_key: bool | UndefinedType = Undefined, + users: Users | UndefinedType = Undefined, + hosts: Hosts | UndefinedType = Undefined, + communities: Communities | UndefinedType = Undefined, + ipv4_acls: Ipv4Acls | UndefinedType = Undefined, + ipv6_acls: Ipv6Acls | UndefinedType = Undefined, + views: Views | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + traps: Traps | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SnmpSettings. + + + Subclass of AvdModel. + + Args: + contact: SNMP contact. + location: + Set SNMP location. Formatted as " + ". + vrfs: + Enable/disable SNMP for one or more VRFs. + Can be used in combination with + "enable_mgmt_interface_vrf" and "enable_inband_mgmt_vrf". + enable_mgmt_interface_vrf: + Enable/disable SNMP for the VRF set with "mgmt_interface_vrf". + Ignored if 'mgmt_ip' or + 'ipv6_mgmt_ip' are not configured for the device. + Can be used in combination with "vrfs" and + "enable_inband_mgmt_vrf". + enable_inband_mgmt_vrf: + Enable/disable SNMP for the VRF set with "inband_mgmt_vrf". + Ignored if inband management is not + configured for the device. + Can be used in combination with "vrfs" and "enable_mgmt_interface_vrf". + compute_local_engineid: Generate a local engineId for SNMP using the 'compute_local_engineid_source' method. + compute_local_engineid_source: + `compute_local_engineid_source` supports: + - `hostname_and_ip` generate a local engineId for SNMP by + hashing via SHA1 + the string generated via the concatenation of the hostname plus the management + IP. + {{ inventory_hostname }} + {{ switch.mgmt_ip }}. + - `system_mac` generate the switch default + engine id for AVD usage. + To use this, `system_mac_address` MUST be set for the device. + The + formula is f5717f + system_mac_address + 00. + compute_v3_user_localized_key: + Requires compute_local_engineid to be `true`. + If enabled, the SNMPv3 passphrases for auth and priv + are transformed using RFC 2574, matching the value they would take in EOS CLI. + The algorithm + requires a local engineId, which is unknown to AVD, hence the necessity to generate one beforehand. + users: + Configuration of local SNMP users. + Configuration of remote SNMP users are currently only possible + using `structured_config`. + + Subclass of AvdList with `UsersItem` items. + hosts: Subclass of AvdList with `HostsItem` items. + communities: communities + ipv4_acls: Subclass of AvdList with `Ipv4AclsItem` items. + ipv6_acls: Subclass of AvdList with `Ipv6AclsItem` items. + views: Subclass of AvdList with `ViewsItem` items. + groups: Subclass of AvdList with `GroupsItem` items. + traps: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class SourceInterfaces(AvdModel): + """Subclass of AvdModel.""" + + class DomainLookup(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "mgmt_interface": {"type": bool, "default": False}, + "inband_mgmt_interface": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + mgmt_interface: bool + """ + Configure an IP Domain Lookup source-interface with the interface set by `mgmt_interface` for the + VRF set by `mgmt_interface_vrf`. + `mgmt_interface` is typically the out-of-band Management interface, + and can be set under the node settings, platform settings or as a group/host var. + + Default value: `False` + """ + inband_mgmt_interface: bool + """ + Configure an IP Domain Lookup source-interface with the interface set by `inband_mgmt_interface` for + the VRF set by `inband_mgmt_vrf`. + `inband_mgmt_interface` is typically a loopback or SVI interface, + and can be set under the node settings. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mgmt_interface: bool | UndefinedType = Undefined, + inband_mgmt_interface: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DomainLookup. + + + Subclass of AvdModel. + + Args: + mgmt_interface: + Configure an IP Domain Lookup source-interface with the interface set by `mgmt_interface` for the + VRF set by `mgmt_interface_vrf`. + `mgmt_interface` is typically the out-of-band Management interface, + and can be set under the node settings, platform settings or as a group/host var. + inband_mgmt_interface: + Configure an IP Domain Lookup source-interface with the interface set by `inband_mgmt_interface` for + the VRF set by `inband_mgmt_vrf`. + `inband_mgmt_interface` is typically a loopback or SVI interface, + and can be set under the node settings. + _custom_data: _custom_data + + """ + + class HttpClient(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "mgmt_interface": {"type": bool, "default": False}, + "inband_mgmt_interface": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + mgmt_interface: bool + """ + Configure an IP HTTP Client source-interface with the interface set by `mgmt_interface` for the VRF + set by `mgmt_interface_vrf`. + `mgmt_interface` is typically the out-of-band Management interface, and + can be set under the node settings, platform settings or as a group/host var. + + Default value: `False` + """ + inband_mgmt_interface: bool + """ + Configure an IP HTTP Client source-interface with the interface set by `inband_mgmt_interface` for + the VRF set by `inband_mgmt_vrf`. + `inband_mgmt_interface` is typically a loopback or SVI interface, + and can be set under the node settings. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mgmt_interface: bool | UndefinedType = Undefined, + inband_mgmt_interface: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + HttpClient. + + + Subclass of AvdModel. + + Args: + mgmt_interface: + Configure an IP HTTP Client source-interface with the interface set by `mgmt_interface` for the VRF + set by `mgmt_interface_vrf`. + `mgmt_interface` is typically the out-of-band Management interface, and + can be set under the node settings, platform settings or as a group/host var. + inband_mgmt_interface: + Configure an IP HTTP Client source-interface with the interface set by `inband_mgmt_interface` for + the VRF set by `inband_mgmt_vrf`. + `inband_mgmt_interface` is typically a loopback or SVI interface, + and can be set under the node settings. + _custom_data: _custom_data + + """ + + class Radius(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "mgmt_interface": {"type": bool, "default": False}, + "inband_mgmt_interface": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + mgmt_interface: bool + """ + Configure an IP Radius source-interface with the interface set by `mgmt_interface` for the VRF set + by `mgmt_interface_vrf`. + `mgmt_interface` is typically the out-of-band Management interface, and can + be set under the node settings, platform settings or as a group/host var. + + Default value: `False` + """ + inband_mgmt_interface: bool + """ + Configure an IP Radius source-interface with the interface set by `inband_mgmt_interface` for the + VRF set by `inband_mgmt_vrf`. + `inband_mgmt_interface` is typically a loopback or SVI interface, and + can be set under the node settings. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mgmt_interface: bool | UndefinedType = Undefined, + inband_mgmt_interface: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Radius. + + + Subclass of AvdModel. + + Args: + mgmt_interface: + Configure an IP Radius source-interface with the interface set by `mgmt_interface` for the VRF set + by `mgmt_interface_vrf`. + `mgmt_interface` is typically the out-of-band Management interface, and can + be set under the node settings, platform settings or as a group/host var. + inband_mgmt_interface: + Configure an IP Radius source-interface with the interface set by `inband_mgmt_interface` for the + VRF set by `inband_mgmt_vrf`. + `inband_mgmt_interface` is typically a loopback or SVI interface, and + can be set under the node settings. + _custom_data: _custom_data + + """ + + class Snmp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "mgmt_interface": {"type": bool, "default": False}, + "inband_mgmt_interface": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + mgmt_interface: bool + """ + Configure a SNMP local-interface with the interface set by `mgmt_interface` for the VRF set by + `mgmt_interface_vrf`. + `mgmt_interface` is typically the out-of-band Management interface, and can be + set under the node settings, platform settings or as a group/host var. + + Default value: `False` + """ + inband_mgmt_interface: bool + """ + Configure a SNMP local-interface with the interface set by `inband_mgmt_interface` for the VRF set + by `inband_mgmt_vrf`. + `inband_mgmt_interface` is typically a loopback or SVI interface, and can be + set under the node settings. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mgmt_interface: bool | UndefinedType = Undefined, + inband_mgmt_interface: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Snmp. + + + Subclass of AvdModel. + + Args: + mgmt_interface: + Configure a SNMP local-interface with the interface set by `mgmt_interface` for the VRF set by + `mgmt_interface_vrf`. + `mgmt_interface` is typically the out-of-band Management interface, and can be + set under the node settings, platform settings or as a group/host var. + inband_mgmt_interface: + Configure a SNMP local-interface with the interface set by `inband_mgmt_interface` for the VRF set + by `inband_mgmt_vrf`. + `inband_mgmt_interface` is typically a loopback or SVI interface, and can be + set under the node settings. + _custom_data: _custom_data + + """ + + class SshClient(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "mgmt_interface": {"type": bool, "default": False}, + "inband_mgmt_interface": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + mgmt_interface: bool + """ + Configure an IP SSH Client source-interface with the interface set by `mgmt_interface` for the VRF + set by `mgmt_interface_vrf`. + `mgmt_interface` is typically the out-of-band Management interface, and + can be set under the node settings, platform settings or as a group/host var. + + Default value: `False` + """ + inband_mgmt_interface: bool + """ + Configure an IP SSH Client source-interface with the interface set by `inband_mgmt_interface` for + the VRF set by `inband_mgmt_vrf`. + `inband_mgmt_interface` is typically a loopback or SVI interface, + and can be set under the node settings. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mgmt_interface: bool | UndefinedType = Undefined, + inband_mgmt_interface: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SshClient. + + + Subclass of AvdModel. + + Args: + mgmt_interface: + Configure an IP SSH Client source-interface with the interface set by `mgmt_interface` for the VRF + set by `mgmt_interface_vrf`. + `mgmt_interface` is typically the out-of-band Management interface, and + can be set under the node settings, platform settings or as a group/host var. + inband_mgmt_interface: + Configure an IP SSH Client source-interface with the interface set by `inband_mgmt_interface` for + the VRF set by `inband_mgmt_vrf`. + `inband_mgmt_interface` is typically a loopback or SVI interface, + and can be set under the node settings. + _custom_data: _custom_data + + """ + + class Tacacs(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "mgmt_interface": {"type": bool, "default": False}, + "inband_mgmt_interface": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + mgmt_interface: bool + """ + Configure an IP Tacacs source-interface with the interface set by `mgmt_interface` for the VRF set + by `mgmt_interface_vrf`. + `mgmt_interface` is typically the out-of-band Management interface, and can + be set under the node settings, platform settings or as a group/host var. + + Default value: `False` + """ + inband_mgmt_interface: bool + """ + Configure an IP Tacacs source-interface with the interface set by `inband_mgmt_interface` for the + VRF set by `inband_mgmt_vrf`. + `inband_mgmt_interface` is typically a loopback or SVI interface, and + can be set under the node settings. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mgmt_interface: bool | UndefinedType = Undefined, + inband_mgmt_interface: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Tacacs. + + + Subclass of AvdModel. + + Args: + mgmt_interface: + Configure an IP Tacacs source-interface with the interface set by `mgmt_interface` for the VRF set + by `mgmt_interface_vrf`. + `mgmt_interface` is typically the out-of-band Management interface, and can + be set under the node settings, platform settings or as a group/host var. + inband_mgmt_interface: + Configure an IP Tacacs source-interface with the interface set by `inband_mgmt_interface` for the + VRF set by `inband_mgmt_vrf`. + `inband_mgmt_interface` is typically a loopback or SVI interface, and + can be set under the node settings. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "domain_lookup": {"type": DomainLookup}, + "http_client": {"type": HttpClient}, + "radius": {"type": Radius}, + "snmp": {"type": Snmp}, + "ssh_client": {"type": SshClient}, + "tacacs": {"type": Tacacs}, + "_custom_data": {"type": dict}, + } + domain_lookup: DomainLookup + """ + IP Domain Lookup source-interfaces. + + Subclass of AvdModel. + """ + http_client: HttpClient + """ + IP HTTP Client source-interfaces. + + Subclass of AvdModel. + """ + radius: Radius + """ + IP Radius source-interfaces. + + Subclass of AvdModel. + """ + snmp: Snmp + """ + SNMP local-interfaces. + + Subclass of AvdModel. + """ + ssh_client: SshClient + """ + IP SSH Client source-interfaces. + + Subclass of AvdModel. + """ + tacacs: Tacacs + """ + IP Tacacs source-interfaces. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + domain_lookup: DomainLookup | UndefinedType = Undefined, + http_client: HttpClient | UndefinedType = Undefined, + radius: Radius | UndefinedType = Undefined, + snmp: Snmp | UndefinedType = Undefined, + ssh_client: SshClient | UndefinedType = Undefined, + tacacs: Tacacs | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SourceInterfaces. + + + Subclass of AvdModel. + + Args: + domain_lookup: + IP Domain Lookup source-interfaces. + + Subclass of AvdModel. + http_client: + IP HTTP Client source-interfaces. + + Subclass of AvdModel. + radius: + IP Radius source-interfaces. + + Subclass of AvdModel. + snmp: + SNMP local-interfaces. + + Subclass of AvdModel. + ssh_client: + IP SSH Client source-interfaces. + + Subclass of AvdModel. + tacacs: + IP Tacacs source-interfaces. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class SviProfilesItem(AvdModel): + """Subclass of AvdModel.""" + + class NodesItem(AvdModel): + """Subclass of AvdModel.""" + + class Ipv6AddressVirtuals(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Ipv6AddressVirtuals._item_type = str + + class IpAddressVirtualSecondaries(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + IpAddressVirtualSecondaries._item_type = str + + class IpVirtualRouterAddresses(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + IpVirtualRouterAddresses._item_type = str + + class Ipv6VirtualRouterAddresses(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Ipv6VirtualRouterAddresses._item_type = str + + class IpHelpersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "ip_helper": {"type": str}, + "source_interface": {"type": str}, + "source_vrf": {"type": str}, + "_custom_data": {"type": dict}, + } + ip_helper: str + """IPv4 DHCP server IP.""" + source_interface: str | None + """Interface name to originate DHCP relay packets to DHCP server.""" + source_vrf: str | None + """VRF to originate DHCP relay packets to DHCP server. If not set, EOS uses the VRF on the SVI.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_helper: str | UndefinedType = Undefined, + source_interface: str | None | UndefinedType = Undefined, + source_vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpHelpersItem. + + + Subclass of AvdModel. + + Args: + ip_helper: IPv4 DHCP server IP. + source_interface: Interface name to originate DHCP relay packets to DHCP server. + source_vrf: VRF to originate DHCP relay packets to DHCP server. If not set, EOS uses the VRF on the SVI. + _custom_data: _custom_data + + """ + + class IpHelpers(AvdIndexedList[str, IpHelpersItem]): + """Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is `ip_helper` (`str`).""" + + _primary_key: ClassVar[str] = "ip_helper" + + IpHelpers._item_type = IpHelpersItem + + class TrunkGroups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + TrunkGroups._item_type = str + + class EvpnL2Multicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "always_redistribute_igmp": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + always_redistribute_igmp: bool | None + """ + Always configure `redistribute igmp` under BGP for the VLAN. Overrides the setting of + `.[].evpn_l2_multicast.always_redistribute_igmp`. + By default `redistribute + igmp` is only configured when `evpn_l2_multicast` is True and `evpn_l3_multicast` for the VRF is + False. + Configuring `redistribute igmp` when both L2 and L3 EVPN Multicast is enabled will take up + additional control-plane and data-plane resources, + but it is required to support forwarding of TTL=1 + multicast traffic within the VLAN. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + always_redistribute_igmp: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnL2Multicast. + + + Subclass of AvdModel. + + Args: + enabled: enabled + always_redistribute_igmp: + Always configure `redistribute igmp` under BGP for the VLAN. Overrides the setting of + `.[].evpn_l2_multicast.always_redistribute_igmp`. + By default `redistribute + igmp` is only configured when `evpn_l2_multicast` is True and `evpn_l3_multicast` for the VRF is + False. + Configuring `redistribute igmp` when both L2 and L3 EVPN Multicast is enabled will take up + additional control-plane and data-plane resources, + but it is required to support forwarding of TTL=1 + multicast traffic within the VLAN. + _custom_data: _custom_data + + """ + + class EvpnL3Multicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, enabled: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + EvpnL3Multicast. + + + Subclass of AvdModel. + + Args: + enabled: enabled + _custom_data: _custom_data + + """ + + class IgmpSnoopingQuerier(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "source_address": {"type": str}, + "version": {"type": int}, + "fast_leave": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Will be enabled automatically if evpn_l2_multicast is enabled.""" + source_address: str | None + """ + IPv4_address + If not set, IP address of "Loopback0" will be used. + """ + version: Literal[1, 2, 3] | None + """IGMP Version (By default EOS uses IGMP version 2 for IGMP querier).""" + fast_leave: bool | None + """Enable IGMP snooping fast-leave feature.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + source_address: str | None | UndefinedType = Undefined, + version: Literal[1, 2, 3] | None | UndefinedType = Undefined, + fast_leave: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IgmpSnoopingQuerier. + + + Subclass of AvdModel. + + Args: + enabled: Will be enabled automatically if evpn_l2_multicast is enabled. + source_address: + IPv4_address + If not set, IP address of "Loopback0" will be used. + version: IGMP Version (By default EOS uses IGMP version 2 for IGMP querier). + fast_leave: Enable IGMP snooping fast-leave feature. + _custom_data: _custom_data + + """ + + class Ospf(AvdModel): + """Subclass of AvdModel.""" + + class MessageDigestKeysItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "hash_algorithm": {"type": str, "default": "sha512"}, + "key": {"type": str}, + "_custom_data": {"type": dict}, + } + id: int | None + hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] + """Default value: `"sha512"`""" + key: str | None + """Type 7 encrypted key.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | None | UndefinedType = Undefined, + hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MessageDigestKeysItem. + + + Subclass of AvdModel. + + Args: + id: id + hash_algorithm: hash_algorithm + key: Type 7 encrypted key. + _custom_data: _custom_data + + """ + + class MessageDigestKeys(AvdList[MessageDigestKeysItem]): + """Subclass of AvdList with `MessageDigestKeysItem` items.""" + + MessageDigestKeys._item_type = MessageDigestKeysItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "point_to_point": {"type": bool, "default": False}, + "area": {"type": str, "default": "0.0.0.0"}, + "cost": {"type": int}, + "authentication": {"type": str}, + "simple_auth_key": {"type": str}, + "message_digest_keys": {"type": MessageDigestKeys}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + point_to_point: bool + """Default value: `False`""" + area: str + """ + OSPF area ID. + + Default value: `"0.0.0.0"` + """ + cost: int | None + """OSPF link cost.""" + authentication: Literal["simple", "message-digest"] | None + simple_auth_key: str | None + """Password used with simple authentication.""" + message_digest_keys: MessageDigestKeys + """Subclass of AvdList with `MessageDigestKeysItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + point_to_point: bool | UndefinedType = Undefined, + area: str | UndefinedType = Undefined, + cost: int | None | UndefinedType = Undefined, + authentication: Literal["simple", "message-digest"] | None | UndefinedType = Undefined, + simple_auth_key: str | None | UndefinedType = Undefined, + message_digest_keys: MessageDigestKeys | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospf. + + + Subclass of AvdModel. + + Args: + enabled: enabled + point_to_point: point_to_point + area: OSPF area ID. + cost: OSPF link cost. + authentication: authentication + simple_auth_key: Password used with simple authentication. + message_digest_keys: Subclass of AvdList with `MessageDigestKeysItem` items. + _custom_data: _custom_data + + """ + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class StructuredConfig(EosCliConfigGen.RouterBgp.VlansItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"structured_config": {"type": StructuredConfig}, "raw_eos_cli": {"type": str}, "_custom_data": {"type": dict}} + structured_config: StructuredConfig + """ + Structured configuration and EOS CLI commands rendered on router_bgp.vlans.[id=]. + This + configuration will not be applied to vlan aware bundles. + + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the Router BGP, VLAN definition in the final EOS configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + structured_config: StructuredConfig | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + structured_config: + Structured configuration and EOS CLI commands rendered on router_bgp.vlans.[id=]. + This + configuration will not be applied to vlan aware bundles. + + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the Router BGP, VLAN definition in the final EOS configuration. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "node": {"type": str}, + "name": {"type": str}, + "enabled": {"type": bool}, + "description": {"type": str}, + "ip_address": {"type": str}, + "ipv6_address": {"type": str}, + "ipv6_enable": {"type": bool}, + "ip_address_virtual": {"type": str}, + "ipv6_address_virtuals": {"type": Ipv6AddressVirtuals}, + "ip_address_virtual_secondaries": {"type": IpAddressVirtualSecondaries}, + "ip_virtual_router_addresses": {"type": IpVirtualRouterAddresses}, + "ipv6_virtual_router_addresses": {"type": Ipv6VirtualRouterAddresses}, + "ipv4_acl_in": {"type": str}, + "ipv4_acl_out": {"type": str}, + "ip_helpers": {"type": IpHelpers}, + "vni_override": {"type": int}, + "rt_override": {"type": str}, + "rd_override": {"type": str}, + "trunk_groups": {"type": TrunkGroups}, + "evpn_l2_multicast": {"type": EvpnL2Multicast}, + "evpn_l3_multicast": {"type": EvpnL3Multicast}, + "igmp_snooping_enabled": {"type": bool}, + "igmp_snooping_querier": {"type": IgmpSnoopingQuerier}, + "vxlan": {"type": bool, "default": True}, + "spanning_tree_priority": {"type": int}, + "mtu": {"type": int}, + "ospf": {"type": Ospf}, + "bgp": {"type": Bgp}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "evpn_l2_multi_domain": {"type": bool}, + "_custom_data": {"type": dict}, + } + node: str + """Node inventory hostname.""" + name: str | None + """VLAN name.""" + enabled: bool | None + """Enable or disable interface.""" + description: str | None + """SVI description. By default set to VLAN name.""" + ip_address: str | None + """IPv4_address/Mask. Usually set under "nodes" to have unique IPv4 addresses per node.""" + ipv6_address: str | None + """IPv6_address/Mask. Usually set under "nodes" to have unique IPv6 addresses per node.""" + ipv6_enable: bool | None + """Explicitly enable/disable link-local IPv6 addressing.""" + ip_address_virtual: str | None + """ + IPv4_address/Mask. + IPv4 VXLAN Anycast IP address. + Conserves IP addresses in VXLAN deployments as it + doesn't require unique IP addresses on each node. + """ + ipv6_address_virtuals: Ipv6AddressVirtuals + """ + IPv6 VXLAN Anycast IP addresses. + Conserves IPv6 addresses in VXLAN deployments as it doesn't require + unique IPv6 addresses on each node. + + + Subclass of AvdList with `str` items. + """ + ip_address_virtual_secondaries: IpAddressVirtualSecondaries + """ + Secondary IPv4 VXLAN Anycast IP addresses. + + Subclass of AvdList with `str` items. + """ + ip_virtual_router_addresses: IpVirtualRouterAddresses + """ + IPv4 VARP addresses. + Requires an IP address to be configured on the SVI. + If ip_address_virtual is + also set, ip_virtual_router_addresses will take precedence + _if_ there is an ip_address configured + for the node. + + + Subclass of AvdList with `str` items. + """ + ipv6_virtual_router_addresses: Ipv6VirtualRouterAddresses + """ + IPv6 VARP addresses. + Requires an IPv6 address to be configured on the SVI. + If ipv6_address_virtuals + is also set, ipv6_virtual_router_addresses will take precedence + _if_ there is an ipv6_address + configured for the node. + + + Subclass of AvdList with `str` items. + """ + ipv4_acl_in: str | None + """ + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports substitution of the field "interface_ip". + """ + ipv4_acl_out: str | None + """ + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports substitution of the field "interface_ip". + """ + ip_helpers: IpHelpers + """ + IP helper for DHCP relay. + + Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is + `ip_helper` (`str`). + """ + vni_override: int | None + """ + By default the VNI will be derived from "mac_vrf_vni_base". + The vni_override allows us to override + this value and statically define it (optional). + """ + rt_override: str | None + """ + By default the MAC VRF RT will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rt_override will default to vni_override if set. + rt_override supports two formats: + - A single number which will be used in the RT fields instead of + mac_vrf_id/mac_vrf_vni (see 'overlay_rt_type' for details). + - A full RT string with colon + separator which will override the full RT. + """ + rd_override: str | None + """ + By default the MAC VRF RD will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rd_override will default to rt_override or + vni_override if set. + + rd_override supports two formats: + - A single number which will be used in + the RD assigned number field instead of mac_vrf_id/mac_vrf_vni (see 'overlay_rd_type' for details). + - A full RD string with colon separator which will override the full RD. + """ + trunk_groups: TrunkGroups + """Subclass of AvdList with `str` items.""" + evpn_l2_multicast: EvpnL2Multicast + """ + Explicitly enable or disable evpn_l2_multicast to override setting of + `.[].evpn_l2_multicast.enabled`. + When evpn_l2_multicast.enabled is set to true + for a vlan or a tenant, "igmp snooping" and "igmp snooping querier" will always be enabled, + overriding those individual settings. + Requires `evpn_multicast` to also be set to `true`. + + + Subclass + of AvdModel. + """ + evpn_l3_multicast: EvpnL3Multicast + """ + Explicitly enable or disable evpn_l3_multicast to override setting of + `.[].evpn_l3_multicast.enabled` and + `.[].vrfs.[].evpn_l3_multicast.enabled`. + Requires `evpn_multicast` to also be + set to `true`. + + + Subclass of AvdModel. + """ + igmp_snooping_enabled: bool | None + """Enable or disable IGMP snooping (Enabled by default on EOS).""" + igmp_snooping_querier: IgmpSnoopingQuerier + """Subclass of AvdModel.""" + vxlan: bool + """ + Extend this SVI over VXLAN. + + Default value: `True` + """ + spanning_tree_priority: int | None + """ + Setting spanning-tree priority per VLAN is only supported with `spanning_tree_mode: rapid-pvst` + under node type settings. + The default priority for rapid-PVST is set under the node type settings + with `spanning_tree_priority` (default=32768). + """ + mtu: int | None + """Interface MTU.""" + ospf: Ospf + """ + OSPF interface configuration. + + Subclass of AvdModel. + """ + bgp: Bgp + """Subclass of AvdModel.""" + raw_eos_cli: str | None + """EOS CLI rendered directly on the VLAN interface in the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config added under vlan_interfaces.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + """ + evpn_l2_multi_domain: bool | None + """ + Explicitly extend SVI to remote EVPN domains. + Overrides + `[].evpn_l2_multi_domain` and + `[].vrfs[].evpn_l2_multi_domain`. + Not supported in conjunction with EVPN vlan + aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` + or `[].vrfs[].svis[].evpn_vlan_bundle`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + node: str | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + enabled: bool | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + ipv6_address: str | None | UndefinedType = Undefined, + ipv6_enable: bool | None | UndefinedType = Undefined, + ip_address_virtual: str | None | UndefinedType = Undefined, + ipv6_address_virtuals: Ipv6AddressVirtuals | UndefinedType = Undefined, + ip_address_virtual_secondaries: IpAddressVirtualSecondaries | UndefinedType = Undefined, + ip_virtual_router_addresses: IpVirtualRouterAddresses | UndefinedType = Undefined, + ipv6_virtual_router_addresses: Ipv6VirtualRouterAddresses | UndefinedType = Undefined, + ipv4_acl_in: str | None | UndefinedType = Undefined, + ipv4_acl_out: str | None | UndefinedType = Undefined, + ip_helpers: IpHelpers | UndefinedType = Undefined, + vni_override: int | None | UndefinedType = Undefined, + rt_override: str | None | UndefinedType = Undefined, + rd_override: str | None | UndefinedType = Undefined, + trunk_groups: TrunkGroups | UndefinedType = Undefined, + evpn_l2_multicast: EvpnL2Multicast | UndefinedType = Undefined, + evpn_l3_multicast: EvpnL3Multicast | UndefinedType = Undefined, + igmp_snooping_enabled: bool | None | UndefinedType = Undefined, + igmp_snooping_querier: IgmpSnoopingQuerier | UndefinedType = Undefined, + vxlan: bool | UndefinedType = Undefined, + spanning_tree_priority: int | None | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + ospf: Ospf | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + evpn_l2_multi_domain: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NodesItem. + + + Subclass of AvdModel. + + Args: + node: Node inventory hostname. + name: VLAN name. + enabled: Enable or disable interface. + description: SVI description. By default set to VLAN name. + ip_address: IPv4_address/Mask. Usually set under "nodes" to have unique IPv4 addresses per node. + ipv6_address: IPv6_address/Mask. Usually set under "nodes" to have unique IPv6 addresses per node. + ipv6_enable: Explicitly enable/disable link-local IPv6 addressing. + ip_address_virtual: + IPv4_address/Mask. + IPv4 VXLAN Anycast IP address. + Conserves IP addresses in VXLAN deployments as it + doesn't require unique IP addresses on each node. + ipv6_address_virtuals: + IPv6 VXLAN Anycast IP addresses. + Conserves IPv6 addresses in VXLAN deployments as it doesn't require + unique IPv6 addresses on each node. + + + Subclass of AvdList with `str` items. + ip_address_virtual_secondaries: + Secondary IPv4 VXLAN Anycast IP addresses. + + Subclass of AvdList with `str` items. + ip_virtual_router_addresses: + IPv4 VARP addresses. + Requires an IP address to be configured on the SVI. + If ip_address_virtual is + also set, ip_virtual_router_addresses will take precedence + _if_ there is an ip_address configured + for the node. + + + Subclass of AvdList with `str` items. + ipv6_virtual_router_addresses: + IPv6 VARP addresses. + Requires an IPv6 address to be configured on the SVI. + If ipv6_address_virtuals + is also set, ipv6_virtual_router_addresses will take precedence + _if_ there is an ipv6_address + configured for the node. + + + Subclass of AvdList with `str` items. + ipv4_acl_in: + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports substitution of the field "interface_ip". + ipv4_acl_out: + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports substitution of the field "interface_ip". + ip_helpers: + IP helper for DHCP relay. + + Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is + `ip_helper` (`str`). + vni_override: + By default the VNI will be derived from "mac_vrf_vni_base". + The vni_override allows us to override + this value and statically define it (optional). + rt_override: + By default the MAC VRF RT will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rt_override will default to vni_override if set. + rt_override supports two formats: + - A single number which will be used in the RT fields instead of + mac_vrf_id/mac_vrf_vni (see 'overlay_rt_type' for details). + - A full RT string with colon + separator which will override the full RT. + rd_override: + By default the MAC VRF RD will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rd_override will default to rt_override or + vni_override if set. + + rd_override supports two formats: + - A single number which will be used in + the RD assigned number field instead of mac_vrf_id/mac_vrf_vni (see 'overlay_rd_type' for details). + - A full RD string with colon separator which will override the full RD. + trunk_groups: Subclass of AvdList with `str` items. + evpn_l2_multicast: + Explicitly enable or disable evpn_l2_multicast to override setting of + `.[].evpn_l2_multicast.enabled`. + When evpn_l2_multicast.enabled is set to true + for a vlan or a tenant, "igmp snooping" and "igmp snooping querier" will always be enabled, + overriding those individual settings. + Requires `evpn_multicast` to also be set to `true`. + + + Subclass + of AvdModel. + evpn_l3_multicast: + Explicitly enable or disable evpn_l3_multicast to override setting of + `.[].evpn_l3_multicast.enabled` and + `.[].vrfs.[].evpn_l3_multicast.enabled`. + Requires `evpn_multicast` to also be + set to `true`. + + + Subclass of AvdModel. + igmp_snooping_enabled: Enable or disable IGMP snooping (Enabled by default on EOS). + igmp_snooping_querier: Subclass of AvdModel. + vxlan: Extend this SVI over VXLAN. + spanning_tree_priority: + Setting spanning-tree priority per VLAN is only supported with `spanning_tree_mode: rapid-pvst` + under node type settings. + The default priority for rapid-PVST is set under the node type settings + with `spanning_tree_priority` (default=32768). + mtu: Interface MTU. + ospf: + OSPF interface configuration. + + Subclass of AvdModel. + bgp: Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the VLAN interface in the final EOS configuration. + structured_config: + Custom structured config added under vlan_interfaces.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + evpn_l2_multi_domain: + Explicitly extend SVI to remote EVPN domains. + Overrides + `[].evpn_l2_multi_domain` and + `[].vrfs[].evpn_l2_multi_domain`. + Not supported in conjunction with EVPN vlan + aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` + or `[].vrfs[].svis[].evpn_vlan_bundle`. + _custom_data: _custom_data + + """ + + class Nodes(AvdIndexedList[str, NodesItem]): + """Subclass of AvdIndexedList with `NodesItem` items. Primary key is `node` (`str`).""" + + _primary_key: ClassVar[str] = "node" + + Nodes._item_type = NodesItem + + class Ipv6AddressVirtuals(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Ipv6AddressVirtuals._item_type = str + + class IpAddressVirtualSecondaries(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + IpAddressVirtualSecondaries._item_type = str + + class IpVirtualRouterAddresses(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + IpVirtualRouterAddresses._item_type = str + + class Ipv6VirtualRouterAddresses(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Ipv6VirtualRouterAddresses._item_type = str + + class IpHelpersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "ip_helper": {"type": str}, + "source_interface": {"type": str}, + "source_vrf": {"type": str}, + "_custom_data": {"type": dict}, + } + ip_helper: str + """IPv4 DHCP server IP.""" + source_interface: str | None + """Interface name to originate DHCP relay packets to DHCP server.""" + source_vrf: str | None + """VRF to originate DHCP relay packets to DHCP server. If not set, EOS uses the VRF on the SVI.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_helper: str | UndefinedType = Undefined, + source_interface: str | None | UndefinedType = Undefined, + source_vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpHelpersItem. + + + Subclass of AvdModel. + + Args: + ip_helper: IPv4 DHCP server IP. + source_interface: Interface name to originate DHCP relay packets to DHCP server. + source_vrf: VRF to originate DHCP relay packets to DHCP server. If not set, EOS uses the VRF on the SVI. + _custom_data: _custom_data + + """ + + class IpHelpers(AvdIndexedList[str, IpHelpersItem]): + """Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is `ip_helper` (`str`).""" + + _primary_key: ClassVar[str] = "ip_helper" + + IpHelpers._item_type = IpHelpersItem + + class TrunkGroups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + TrunkGroups._item_type = str + + class EvpnL2Multicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "always_redistribute_igmp": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + always_redistribute_igmp: bool | None + """ + Always configure `redistribute igmp` under BGP for the VLAN. Overrides the setting of + `.[].evpn_l2_multicast.always_redistribute_igmp`. + By default `redistribute + igmp` is only configured when `evpn_l2_multicast` is True and `evpn_l3_multicast` for the VRF is + False. + Configuring `redistribute igmp` when both L2 and L3 EVPN Multicast is enabled will take up + additional control-plane and data-plane resources, + but it is required to support forwarding of TTL=1 + multicast traffic within the VLAN. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + always_redistribute_igmp: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnL2Multicast. + + + Subclass of AvdModel. + + Args: + enabled: enabled + always_redistribute_igmp: + Always configure `redistribute igmp` under BGP for the VLAN. Overrides the setting of + `.[].evpn_l2_multicast.always_redistribute_igmp`. + By default `redistribute + igmp` is only configured when `evpn_l2_multicast` is True and `evpn_l3_multicast` for the VRF is + False. + Configuring `redistribute igmp` when both L2 and L3 EVPN Multicast is enabled will take up + additional control-plane and data-plane resources, + but it is required to support forwarding of TTL=1 + multicast traffic within the VLAN. + _custom_data: _custom_data + + """ + + class EvpnL3Multicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, enabled: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + EvpnL3Multicast. + + + Subclass of AvdModel. + + Args: + enabled: enabled + _custom_data: _custom_data + + """ + + class IgmpSnoopingQuerier(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "source_address": {"type": str}, + "version": {"type": int}, + "fast_leave": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Will be enabled automatically if evpn_l2_multicast is enabled.""" + source_address: str | None + """ + IPv4_address + If not set, IP address of "Loopback0" will be used. + """ + version: Literal[1, 2, 3] | None + """IGMP Version (By default EOS uses IGMP version 2 for IGMP querier).""" + fast_leave: bool | None + """Enable IGMP snooping fast-leave feature.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + source_address: str | None | UndefinedType = Undefined, + version: Literal[1, 2, 3] | None | UndefinedType = Undefined, + fast_leave: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IgmpSnoopingQuerier. + + + Subclass of AvdModel. + + Args: + enabled: Will be enabled automatically if evpn_l2_multicast is enabled. + source_address: + IPv4_address + If not set, IP address of "Loopback0" will be used. + version: IGMP Version (By default EOS uses IGMP version 2 for IGMP querier). + fast_leave: Enable IGMP snooping fast-leave feature. + _custom_data: _custom_data + + """ + + class Ospf(AvdModel): + """Subclass of AvdModel.""" + + class MessageDigestKeysItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "hash_algorithm": {"type": str, "default": "sha512"}, + "key": {"type": str}, + "_custom_data": {"type": dict}, + } + id: int | None + hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] + """Default value: `"sha512"`""" + key: str | None + """Type 7 encrypted key.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | None | UndefinedType = Undefined, + hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MessageDigestKeysItem. + + + Subclass of AvdModel. + + Args: + id: id + hash_algorithm: hash_algorithm + key: Type 7 encrypted key. + _custom_data: _custom_data + + """ + + class MessageDigestKeys(AvdList[MessageDigestKeysItem]): + """Subclass of AvdList with `MessageDigestKeysItem` items.""" + + MessageDigestKeys._item_type = MessageDigestKeysItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "point_to_point": {"type": bool, "default": False}, + "area": {"type": str, "default": "0.0.0.0"}, + "cost": {"type": int}, + "authentication": {"type": str}, + "simple_auth_key": {"type": str}, + "message_digest_keys": {"type": MessageDigestKeys}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + point_to_point: bool + """Default value: `False`""" + area: str + """ + OSPF area ID. + + Default value: `"0.0.0.0"` + """ + cost: int | None + """OSPF link cost.""" + authentication: Literal["simple", "message-digest"] | None + simple_auth_key: str | None + """Password used with simple authentication.""" + message_digest_keys: MessageDigestKeys + """Subclass of AvdList with `MessageDigestKeysItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + point_to_point: bool | UndefinedType = Undefined, + area: str | UndefinedType = Undefined, + cost: int | None | UndefinedType = Undefined, + authentication: Literal["simple", "message-digest"] | None | UndefinedType = Undefined, + simple_auth_key: str | None | UndefinedType = Undefined, + message_digest_keys: MessageDigestKeys | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospf. + + + Subclass of AvdModel. + + Args: + enabled: enabled + point_to_point: point_to_point + area: OSPF area ID. + cost: OSPF link cost. + authentication: authentication + simple_auth_key: Password used with simple authentication. + message_digest_keys: Subclass of AvdList with `MessageDigestKeysItem` items. + _custom_data: _custom_data + + """ + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class StructuredConfig(EosCliConfigGen.RouterBgp.VlansItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"structured_config": {"type": StructuredConfig}, "raw_eos_cli": {"type": str}, "_custom_data": {"type": dict}} + structured_config: StructuredConfig + """ + Structured configuration and EOS CLI commands rendered on router_bgp.vlans.[id=]. + This + configuration will not be applied to vlan aware bundles. + + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the Router BGP, VLAN definition in the final EOS configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + structured_config: StructuredConfig | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + structured_config: + Structured configuration and EOS CLI commands rendered on router_bgp.vlans.[id=]. + This + configuration will not be applied to vlan aware bundles. + + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the Router BGP, VLAN definition in the final EOS configuration. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "profile": {"type": str}, + "parent_profile": {"type": str}, + "nodes": {"type": Nodes}, + "name": {"type": str}, + "enabled": {"type": bool}, + "description": {"type": str}, + "ip_address": {"type": str}, + "ipv6_address": {"type": str}, + "ipv6_enable": {"type": bool}, + "ip_address_virtual": {"type": str}, + "ipv6_address_virtuals": {"type": Ipv6AddressVirtuals}, + "ip_address_virtual_secondaries": {"type": IpAddressVirtualSecondaries}, + "ip_virtual_router_addresses": {"type": IpVirtualRouterAddresses}, + "ipv6_virtual_router_addresses": {"type": Ipv6VirtualRouterAddresses}, + "ipv4_acl_in": {"type": str}, + "ipv4_acl_out": {"type": str}, + "ip_helpers": {"type": IpHelpers}, + "vni_override": {"type": int}, + "rt_override": {"type": str}, + "rd_override": {"type": str}, + "trunk_groups": {"type": TrunkGroups}, + "evpn_l2_multicast": {"type": EvpnL2Multicast}, + "evpn_l3_multicast": {"type": EvpnL3Multicast}, + "igmp_snooping_enabled": {"type": bool}, + "igmp_snooping_querier": {"type": IgmpSnoopingQuerier}, + "vxlan": {"type": bool, "default": True}, + "spanning_tree_priority": {"type": int}, + "mtu": {"type": int}, + "ospf": {"type": Ospf}, + "bgp": {"type": Bgp}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "evpn_l2_multi_domain": {"type": bool}, + "_custom_data": {"type": dict}, + } + profile: str + """Profile name.""" + parent_profile: str | None + """ + Parent SVI profile name to apply. + svi_profiles can refer to another svi_profile to inherit settings + in up to two levels (svi -> svi_profile -> svi_parent_profile). + """ + nodes: Nodes + """ + Define node specific configuration, such as unique IP addresses. + Any keys set here will be merged + onto the SVI config, except `structured_config` keys which will replace the `structured_config` set + on SVI level. + + + Subclass of AvdIndexedList with `NodesItem` items. Primary key is `node` (`str`). + """ + name: str | None + """VLAN name.""" + enabled: bool | None + """Enable or disable interface.""" + description: str | None + """SVI description. By default set to VLAN name.""" + ip_address: str | None + """IPv4_address/Mask. Usually set under "nodes" to have unique IPv4 addresses per node.""" + ipv6_address: str | None + """IPv6_address/Mask. Usually set under "nodes" to have unique IPv6 addresses per node.""" + ipv6_enable: bool | None + """Explicitly enable/disable link-local IPv6 addressing.""" + ip_address_virtual: str | None + """ + IPv4_address/Mask. + IPv4 VXLAN Anycast IP address. + Conserves IP addresses in VXLAN deployments as it + doesn't require unique IP addresses on each node. + """ + ipv6_address_virtuals: Ipv6AddressVirtuals + """ + IPv6 VXLAN Anycast IP addresses. + Conserves IPv6 addresses in VXLAN deployments as it doesn't require + unique IPv6 addresses on each node. + + + Subclass of AvdList with `str` items. + """ + ip_address_virtual_secondaries: IpAddressVirtualSecondaries + """ + Secondary IPv4 VXLAN Anycast IP addresses. + + Subclass of AvdList with `str` items. + """ + ip_virtual_router_addresses: IpVirtualRouterAddresses + """ + IPv4 VARP addresses. + Requires an IP address to be configured on the SVI. + If ip_address_virtual is + also set, ip_virtual_router_addresses will take precedence + _if_ there is an ip_address configured + for the node. + + + Subclass of AvdList with `str` items. + """ + ipv6_virtual_router_addresses: Ipv6VirtualRouterAddresses + """ + IPv6 VARP addresses. + Requires an IPv6 address to be configured on the SVI. + If ipv6_address_virtuals + is also set, ipv6_virtual_router_addresses will take precedence + _if_ there is an ipv6_address + configured for the node. + + + Subclass of AvdList with `str` items. + """ + ipv4_acl_in: str | None + """ + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports substitution of the field "interface_ip". + """ + ipv4_acl_out: str | None + """ + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports substitution of the field "interface_ip". + """ + ip_helpers: IpHelpers + """ + IP helper for DHCP relay. + + Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is + `ip_helper` (`str`). + """ + vni_override: int | None + """ + By default the VNI will be derived from "mac_vrf_vni_base". + The vni_override allows us to override + this value and statically define it (optional). + """ + rt_override: str | None + """ + By default the MAC VRF RT will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rt_override will default to vni_override if set. + rt_override supports two formats: + - A single number which will be used in the RT fields instead of + mac_vrf_id/mac_vrf_vni (see 'overlay_rt_type' for details). + - A full RT string with colon + separator which will override the full RT. + """ + rd_override: str | None + """ + By default the MAC VRF RD will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rd_override will default to rt_override or + vni_override if set. + + rd_override supports two formats: + - A single number which will be used in + the RD assigned number field instead of mac_vrf_id/mac_vrf_vni (see 'overlay_rd_type' for details). + - A full RD string with colon separator which will override the full RD. + """ + trunk_groups: TrunkGroups + """Subclass of AvdList with `str` items.""" + evpn_l2_multicast: EvpnL2Multicast + """ + Explicitly enable or disable evpn_l2_multicast to override setting of + `.[].evpn_l2_multicast.enabled`. + When evpn_l2_multicast.enabled is set to true + for a vlan or a tenant, "igmp snooping" and "igmp snooping querier" will always be enabled, + overriding those individual settings. + Requires `evpn_multicast` to also be set to `true`. + + + Subclass + of AvdModel. + """ + evpn_l3_multicast: EvpnL3Multicast + """ + Explicitly enable or disable evpn_l3_multicast to override setting of + `.[].evpn_l3_multicast.enabled` and + `.[].vrfs.[].evpn_l3_multicast.enabled`. + Requires `evpn_multicast` to also be + set to `true`. + + + Subclass of AvdModel. + """ + igmp_snooping_enabled: bool | None + """Enable or disable IGMP snooping (Enabled by default on EOS).""" + igmp_snooping_querier: IgmpSnoopingQuerier + """Subclass of AvdModel.""" + vxlan: bool + """ + Extend this SVI over VXLAN. + + Default value: `True` + """ + spanning_tree_priority: int | None + """ + Setting spanning-tree priority per VLAN is only supported with `spanning_tree_mode: rapid-pvst` + under node type settings. + The default priority for rapid-PVST is set under the node type settings + with `spanning_tree_priority` (default=32768). + """ + mtu: int | None + """Interface MTU.""" + ospf: Ospf + """ + OSPF interface configuration. + + Subclass of AvdModel. + """ + bgp: Bgp + """Subclass of AvdModel.""" + raw_eos_cli: str | None + """EOS CLI rendered directly on the VLAN interface in the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config added under vlan_interfaces.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + """ + evpn_l2_multi_domain: bool | None + """ + Explicitly extend SVI to remote EVPN domains. + Overrides + `[].evpn_l2_multi_domain` and + `[].vrfs[].evpn_l2_multi_domain`. + Not supported in conjunction with EVPN vlan + aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` + or `[].vrfs[].svis[].evpn_vlan_bundle`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + parent_profile: str | None | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + enabled: bool | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + ipv6_address: str | None | UndefinedType = Undefined, + ipv6_enable: bool | None | UndefinedType = Undefined, + ip_address_virtual: str | None | UndefinedType = Undefined, + ipv6_address_virtuals: Ipv6AddressVirtuals | UndefinedType = Undefined, + ip_address_virtual_secondaries: IpAddressVirtualSecondaries | UndefinedType = Undefined, + ip_virtual_router_addresses: IpVirtualRouterAddresses | UndefinedType = Undefined, + ipv6_virtual_router_addresses: Ipv6VirtualRouterAddresses | UndefinedType = Undefined, + ipv4_acl_in: str | None | UndefinedType = Undefined, + ipv4_acl_out: str | None | UndefinedType = Undefined, + ip_helpers: IpHelpers | UndefinedType = Undefined, + vni_override: int | None | UndefinedType = Undefined, + rt_override: str | None | UndefinedType = Undefined, + rd_override: str | None | UndefinedType = Undefined, + trunk_groups: TrunkGroups | UndefinedType = Undefined, + evpn_l2_multicast: EvpnL2Multicast | UndefinedType = Undefined, + evpn_l3_multicast: EvpnL3Multicast | UndefinedType = Undefined, + igmp_snooping_enabled: bool | None | UndefinedType = Undefined, + igmp_snooping_querier: IgmpSnoopingQuerier | UndefinedType = Undefined, + vxlan: bool | UndefinedType = Undefined, + spanning_tree_priority: int | None | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + ospf: Ospf | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + evpn_l2_multi_domain: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SviProfilesItem. + + + Subclass of AvdModel. + + Args: + profile: Profile name. + parent_profile: + Parent SVI profile name to apply. + svi_profiles can refer to another svi_profile to inherit settings + in up to two levels (svi -> svi_profile -> svi_parent_profile). + nodes: + Define node specific configuration, such as unique IP addresses. + Any keys set here will be merged + onto the SVI config, except `structured_config` keys which will replace the `structured_config` set + on SVI level. + + + Subclass of AvdIndexedList with `NodesItem` items. Primary key is `node` (`str`). + name: VLAN name. + enabled: Enable or disable interface. + description: SVI description. By default set to VLAN name. + ip_address: IPv4_address/Mask. Usually set under "nodes" to have unique IPv4 addresses per node. + ipv6_address: IPv6_address/Mask. Usually set under "nodes" to have unique IPv6 addresses per node. + ipv6_enable: Explicitly enable/disable link-local IPv6 addressing. + ip_address_virtual: + IPv4_address/Mask. + IPv4 VXLAN Anycast IP address. + Conserves IP addresses in VXLAN deployments as it + doesn't require unique IP addresses on each node. + ipv6_address_virtuals: + IPv6 VXLAN Anycast IP addresses. + Conserves IPv6 addresses in VXLAN deployments as it doesn't require + unique IPv6 addresses on each node. + + + Subclass of AvdList with `str` items. + ip_address_virtual_secondaries: + Secondary IPv4 VXLAN Anycast IP addresses. + + Subclass of AvdList with `str` items. + ip_virtual_router_addresses: + IPv4 VARP addresses. + Requires an IP address to be configured on the SVI. + If ip_address_virtual is + also set, ip_virtual_router_addresses will take precedence + _if_ there is an ip_address configured + for the node. + + + Subclass of AvdList with `str` items. + ipv6_virtual_router_addresses: + IPv6 VARP addresses. + Requires an IPv6 address to be configured on the SVI. + If ipv6_address_virtuals + is also set, ipv6_virtual_router_addresses will take precedence + _if_ there is an ipv6_address + configured for the node. + + + Subclass of AvdList with `str` items. + ipv4_acl_in: + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports substitution of the field "interface_ip". + ipv4_acl_out: + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports substitution of the field "interface_ip". + ip_helpers: + IP helper for DHCP relay. + + Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is + `ip_helper` (`str`). + vni_override: + By default the VNI will be derived from "mac_vrf_vni_base". + The vni_override allows us to override + this value and statically define it (optional). + rt_override: + By default the MAC VRF RT will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rt_override will default to vni_override if set. + rt_override supports two formats: + - A single number which will be used in the RT fields instead of + mac_vrf_id/mac_vrf_vni (see 'overlay_rt_type' for details). + - A full RT string with colon + separator which will override the full RT. + rd_override: + By default the MAC VRF RD will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rd_override will default to rt_override or + vni_override if set. + + rd_override supports two formats: + - A single number which will be used in + the RD assigned number field instead of mac_vrf_id/mac_vrf_vni (see 'overlay_rd_type' for details). + - A full RD string with colon separator which will override the full RD. + trunk_groups: Subclass of AvdList with `str` items. + evpn_l2_multicast: + Explicitly enable or disable evpn_l2_multicast to override setting of + `.[].evpn_l2_multicast.enabled`. + When evpn_l2_multicast.enabled is set to true + for a vlan or a tenant, "igmp snooping" and "igmp snooping querier" will always be enabled, + overriding those individual settings. + Requires `evpn_multicast` to also be set to `true`. + + + Subclass + of AvdModel. + evpn_l3_multicast: + Explicitly enable or disable evpn_l3_multicast to override setting of + `.[].evpn_l3_multicast.enabled` and + `.[].vrfs.[].evpn_l3_multicast.enabled`. + Requires `evpn_multicast` to also be + set to `true`. + + + Subclass of AvdModel. + igmp_snooping_enabled: Enable or disable IGMP snooping (Enabled by default on EOS). + igmp_snooping_querier: Subclass of AvdModel. + vxlan: Extend this SVI over VXLAN. + spanning_tree_priority: + Setting spanning-tree priority per VLAN is only supported with `spanning_tree_mode: rapid-pvst` + under node type settings. + The default priority for rapid-PVST is set under the node type settings + with `spanning_tree_priority` (default=32768). + mtu: Interface MTU. + ospf: + OSPF interface configuration. + + Subclass of AvdModel. + bgp: Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the VLAN interface in the final EOS configuration. + structured_config: + Custom structured config added under vlan_interfaces.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + evpn_l2_multi_domain: + Explicitly extend SVI to remote EVPN domains. + Overrides + `[].evpn_l2_multi_domain` and + `[].vrfs[].evpn_l2_multi_domain`. + Not supported in conjunction with EVPN vlan + aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` + or `[].vrfs[].svis[].evpn_vlan_bundle`. + _custom_data: _custom_data + + """ + + class SviProfiles(AvdIndexedList[str, SviProfilesItem]): + """Subclass of AvdIndexedList with `SviProfilesItem` items. Primary key is `profile` (`str`).""" + + _primary_key: ClassVar[str] = "profile" + + SviProfiles._item_type = SviProfilesItem + + class TrunkGroups(AvdModel): + """Subclass of AvdModel.""" + + class Mlag(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str, "default": "MLAG"}, "_custom_data": {"type": dict}} + name: str + """Default value: `"MLAG"`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, name: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Mlag. + + + Subclass of AvdModel. + + Args: + name: name + _custom_data: _custom_data + + """ + + class MlagL3(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str, "default": "MLAG"}, "_custom_data": {"type": dict}} + name: str + """Default value: `"MLAG"`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, name: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + MlagL3. + + + Subclass of AvdModel. + + Args: + name: name + _custom_data: _custom_data + + """ + + class Uplink(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str, "default": "UPLINK"}, "_custom_data": {"type": dict}} + name: str + """Default value: `"UPLINK"`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, name: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + Uplink. + + + Subclass of AvdModel. + + Args: + name: name + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"mlag": {"type": Mlag}, "mlag_l3": {"type": MlagL3}, "uplink": {"type": Uplink}, "_custom_data": {"type": dict}} + mlag: Mlag + """ + Trunk Group used for MLAG VLAN (Typically VLAN 4094). + + + Subclass of AvdModel. + """ + mlag_l3: MlagL3 + """ + Trunk Group used for MLAG L3 peering VLAN and for VRF L3 peering VLANs (Typically VLAN 4093). + Subclass of AvdModel. + """ + uplink: Uplink + """ + Trunk Group used on L2 Leaf switches when "enable_trunk_groups" is set. + + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mlag: Mlag | UndefinedType = Undefined, + mlag_l3: MlagL3 | UndefinedType = Undefined, + uplink: Uplink | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + TrunkGroups. + + + Subclass of AvdModel. + + Args: + mlag: + Trunk Group used for MLAG VLAN (Typically VLAN 4094). + + + Subclass of AvdModel. + mlag_l3: + Trunk Group used for MLAG L3 peering VLAN and for VRF L3 peering VLANs (Typically VLAN 4093). + Subclass of AvdModel. + uplink: + Trunk Group used on L2 Leaf switches when "enable_trunk_groups" is set. + + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class UnderlayMulticastAnycastRp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"mode": {"type": str, "default": "pim"}, "_custom_data": {"type": dict}} + mode: Literal["pim", "msdp"] + """Default value: `"pim"`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, mode: Literal["pim", "msdp"] | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + UnderlayMulticastAnycastRp. + + + Subclass of AvdModel. + + Args: + mode: mode + _custom_data: _custom_data + + """ + + class UnderlayMulticastRpsItem(AvdModel): + """Subclass of AvdModel.""" + + class NodesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "loopback_number": {"type": int}, + "description": {"type": str, "default": "PIM RP"}, + "_custom_data": {"type": dict}, + } + name: str + """Hostname.""" + loopback_number: int + description: str + """ + Interface description. + + Default value: `"PIM RP"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + loopback_number: int | UndefinedType = Undefined, + description: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NodesItem. + + + Subclass of AvdModel. + + Args: + name: Hostname. + loopback_number: loopback_number + description: Interface description. + _custom_data: _custom_data + + """ + + class Nodes(AvdIndexedList[str, NodesItem]): + """Subclass of AvdIndexedList with `NodesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Nodes._item_type = NodesItem + + class Groups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Groups._item_type = str + + _fields: ClassVar[dict] = { + "rp": {"type": str}, + "nodes": {"type": Nodes}, + "groups": {"type": Groups}, + "access_list_name": {"type": str}, + "_custom_data": {"type": dict}, + } + rp: str + """RP IPv4 address.""" + nodes: Nodes + """ + List of nodes where a Loopback interface with the RP address will be configured. + + + Subclass of + AvdIndexedList with `NodesItem` items. Primary key is `name` (`str`). + """ + groups: Groups + """ + List of groups to associate with the RP address set in 'rp'. + If access_list_name is set, a standard + access-list will be configured matching these groups. + Otherwise the groups are configured directly + on the RP command. + + + Subclass of AvdList with `str` items. + """ + access_list_name: str | None + """Name of standard Access-List.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + rp: str | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + access_list_name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + UnderlayMulticastRpsItem. + + + Subclass of AvdModel. + + Args: + rp: RP IPv4 address. + nodes: + List of nodes where a Loopback interface with the RP address will be configured. + + + Subclass of + AvdIndexedList with `NodesItem` items. Primary key is `name` (`str`). + groups: + List of groups to associate with the RP address set in 'rp'. + If access_list_name is set, a standard + access-list will be configured matching these groups. + Otherwise the groups are configured directly + on the RP command. + + + Subclass of AvdList with `str` items. + access_list_name: Name of standard Access-List. + _custom_data: _custom_data + + """ + + class UnderlayMulticastRps(AvdIndexedList[str, UnderlayMulticastRpsItem]): + """Subclass of AvdIndexedList with `UnderlayMulticastRpsItem` items. Primary key is `rp` (`str`).""" + + _primary_key: ClassVar[str] = "rp" + + UnderlayMulticastRps._item_type = UnderlayMulticastRpsItem + + class UnderlayOspfAuthentication(AvdModel): + """Subclass of AvdModel.""" + + class MessageDigestKeysItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "hash_algorithm": {"type": str, "default": "sha512"}, + "key": {"type": str}, + "_custom_data": {"type": dict}, + } + id: int + hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] + """Default value: `"sha512"`""" + key: str + """ + Key password. + Only plaintext passwords are supported here as `eos_designs` will encrypt the password + for each individual underlay interface. + To protect the password at rest it is strongly recommended + to make use of Ansible Vault or similar. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | UndefinedType = Undefined, + key: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MessageDigestKeysItem. + + + Subclass of AvdModel. + + Args: + id: id + hash_algorithm: hash_algorithm + key: + Key password. + Only plaintext passwords are supported here as `eos_designs` will encrypt the password + for each individual underlay interface. + To protect the password at rest it is strongly recommended + to make use of Ansible Vault or similar. + _custom_data: _custom_data + + """ + + class MessageDigestKeys(AvdIndexedList[int, MessageDigestKeysItem]): + """Subclass of AvdIndexedList with `MessageDigestKeysItem` items. Primary key is `id` (`int`).""" + + _primary_key: ClassVar[str] = "id" + + MessageDigestKeys._item_type = MessageDigestKeysItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "message_digest_keys": {"type": MessageDigestKeys}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + message_digest_keys: MessageDigestKeys + """Subclass of AvdIndexedList with `MessageDigestKeysItem` items. Primary key is `id` (`int`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + message_digest_keys: MessageDigestKeys | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + UnderlayOspfAuthentication. + + + Subclass of AvdModel. + + Args: + enabled: enabled + message_digest_keys: Subclass of AvdIndexedList with `MessageDigestKeysItem` items. Primary key is `id` (`int`). + _custom_data: _custom_data + + """ + + class UplinkPtp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enable": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enable: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, enable: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + UplinkPtp. + + + Subclass of AvdModel. + + Args: + enable: enable + _custom_data: _custom_data + + """ + + class WanCarriersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "description": {"type": str}, + "path_group": {"type": str}, + "trusted": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + name: str + """Carrier name.""" + description: str | None + """Additional information about the carrier for documentation purposes.""" + path_group: str + """The path-group to which this carrier belongs.""" + trusted: bool + """ + Set this to `true` to mark this carrier as "trusted". + WAN interfaces require an inbound access-list + to be set unless the carrier is "trusted". + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + path_group: str | UndefinedType = Undefined, + trusted: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + WanCarriersItem. + + + Subclass of AvdModel. + + Args: + name: Carrier name. + description: Additional information about the carrier for documentation purposes. + path_group: The path-group to which this carrier belongs. + trusted: + Set this to `true` to mark this carrier as "trusted". + WAN interfaces require an inbound access-list + to be set unless the carrier is "trusted". + _custom_data: _custom_data + + """ + + class WanCarriers(AvdIndexedList[str, WanCarriersItem]): + """Subclass of AvdIndexedList with `WanCarriersItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + WanCarriers._item_type = WanCarriersItem + + class WanHa(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"lan_ha_path_group_name": {"type": str, "default": "LAN_HA"}, "_custom_data": {"type": dict}} + lan_ha_path_group_name: str + """ + When WAN HA is enabled for a site if `wan_mode: cv-pathfinder`, a default path-group is injected to + form DPS tunnels over LAN. + This key allows to overwrite the default LAN HA path-group name. + + Default value: `"LAN_HA"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, lan_ha_path_group_name: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + WanHa. + + + Subclass of AvdModel. + + Args: + lan_ha_path_group_name: + When WAN HA is enabled for a site if `wan_mode: cv-pathfinder`, a default path-group is injected to + form DPS tunnels over LAN. + This key allows to overwrite the default LAN HA path-group name. + _custom_data: _custom_data + + """ + + class WanIpsecProfiles(AvdModel): + """Subclass of AvdModel.""" + + class ControlPlane(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "ike_policy_name": {"type": str, "default": "CP-IKE-POLICY"}, + "sa_policy_name": {"type": str, "default": "CP-SA-POLICY"}, + "profile_name": {"type": str, "default": "CP-PROFILE"}, + "shared_key": {"type": str}, + "_custom_data": {"type": dict}, + } + ike_policy_name: str + """ + Name of the IKE policy. + + Default value: `"CP-IKE-POLICY"` + """ + sa_policy_name: str + """ + Name of the SA policy. + + Default value: `"CP-SA-POLICY"` + """ + profile_name: str + """ + Name of the IPSec profile. + + Default value: `"CP-PROFILE"` + """ + shared_key: str + """ + The IPSec shared key. + This variable is sensitive and SHOULD be configured using some vault + mechanism. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ike_policy_name: str | UndefinedType = Undefined, + sa_policy_name: str | UndefinedType = Undefined, + profile_name: str | UndefinedType = Undefined, + shared_key: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ControlPlane. + + + Subclass of AvdModel. + + Args: + ike_policy_name: Name of the IKE policy. + sa_policy_name: Name of the SA policy. + profile_name: Name of the IPSec profile. + shared_key: + The IPSec shared key. + This variable is sensitive and SHOULD be configured using some vault + mechanism. + _custom_data: _custom_data + + """ + + class DataPlane(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "ike_policy_name": {"type": str, "default": "DP-IKE-POLICY"}, + "sa_policy_name": {"type": str, "default": "DP-SA-POLICY"}, + "profile_name": {"type": str, "default": "DP-PROFILE"}, + "shared_key": {"type": str}, + "_custom_data": {"type": dict}, + } + ike_policy_name: str + """ + Name of the IKE policy. + + Default value: `"DP-IKE-POLICY"` + """ + sa_policy_name: str + """ + Name of the SA policy. + + Default value: `"DP-SA-POLICY"` + """ + profile_name: str + """ + Name of the IPSec profile. + + Default value: `"DP-PROFILE"` + """ + shared_key: str + """ + The type 7 encrypted IPSec shared key. + This variable is sensitive and should be configured using + some vault mechanism. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ike_policy_name: str | UndefinedType = Undefined, + sa_policy_name: str | UndefinedType = Undefined, + profile_name: str | UndefinedType = Undefined, + shared_key: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DataPlane. + + + Subclass of AvdModel. + + Args: + ike_policy_name: Name of the IKE policy. + sa_policy_name: Name of the SA policy. + profile_name: Name of the IPSec profile. + shared_key: + The type 7 encrypted IPSec shared key. + This variable is sensitive and should be configured using + some vault mechanism. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"control_plane": {"type": ControlPlane}, "data_plane": {"type": DataPlane}, "_custom_data": {"type": dict}} + control_plane: ControlPlane + """Subclass of AvdModel.""" + data_plane: DataPlane + """ + If `data_plane` is not defined, `control_plane` information is used for both. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + control_plane: ControlPlane | UndefinedType = Undefined, + data_plane: DataPlane | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + WanIpsecProfiles. + + + Subclass of AvdModel. + + Args: + control_plane: Subclass of AvdModel. + data_plane: + If `data_plane` is not defined, `control_plane` information is used for both. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class WanPathGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class Ipsec(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "dynamic_peers": {"type": bool, "default": True}, + "static_peers": {"type": bool, "default": True}, + "_custom_data": {"type": dict}, + } + dynamic_peers: bool + """ + Enable IPSec for dynamic peers. + + Default value: `True` + """ + static_peers: bool + """ + Enable IPSec for static peers. + + Default value: `True` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + dynamic_peers: bool | UndefinedType = Undefined, + static_peers: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipsec. + + + Subclass of AvdModel. + + Args: + dynamic_peers: Enable IPSec for dynamic peers. + static_peers: Enable IPSec for static peers. + _custom_data: _custom_data + + """ + + class ImportPathGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"remote": {"type": str}, "local": {"type": str}, "_custom_data": {"type": dict}} + remote: str | None + """Remote path-group to import.""" + local: str | None + """Optional, if not set, the path-group `name` is used as local.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + remote: str | None | UndefinedType = Undefined, + local: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ImportPathGroupsItem. + + + Subclass of AvdModel. + + Args: + remote: Remote path-group to import. + local: Optional, if not set, the path-group `name` is used as local. + _custom_data: _custom_data + + """ + + class ImportPathGroups(AvdList[ImportPathGroupsItem]): + """Subclass of AvdList with `ImportPathGroupsItem` items.""" + + ImportPathGroups._item_type = ImportPathGroupsItem + + class DpsKeepalive(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"interval": {"type": str}, "failure_threshold": {"type": int, "default": 5}, "_custom_data": {"type": dict}} + interval: str | None + """ + Interval in milliseconds. Valid values are 50-60000 | "auto". + + When auto, the interval and + failure_threshold are automatically determined based on + path state. + """ + failure_threshold: int + """ + Failure threshold in number of lost keep-alive messages. + + Default value: `5` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: str | None | UndefinedType = Undefined, + failure_threshold: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DpsKeepalive. + + + Subclass of AvdModel. + + Args: + interval: + Interval in milliseconds. Valid values are 50-60000 | "auto". + + When auto, the interval and + failure_threshold are automatically determined based on + path state. + failure_threshold: Failure threshold in number of lost keep-alive messages. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "id": {"type": int}, + "description": {"type": str}, + "ipsec": {"type": Ipsec}, + "import_path_groups": {"type": ImportPathGroups}, + "default_preference": {"type": str, "default": "preferred"}, + "excluded_from_default_policy": {"type": bool, "default": False}, + "dps_keepalive": {"type": DpsKeepalive}, + "_custom_data": {"type": dict}, + } + name: str + """Path-group name.""" + id: int + """ + Path-group id. + Required until an auto ID algorithm is implemented. + """ + description: str | None + """Additional information about the path-group for documentation purposes.""" + ipsec: Ipsec + """ + Configuration of IPSec at the path-group level. + + Subclass of AvdModel. + """ + import_path_groups: ImportPathGroups + """ + List of path-groups to import in this path-group. + + Subclass of AvdList with `ImportPathGroupsItem` + items. + """ + default_preference: str + """ + Preference value used when a preference is not given for a path-group in the + `wan_virtual_topologies.policies` input or when + the path-group is used in an auto generated policy + except if `excluded_from_default_policy` is set to `true. + + Valid values are 1-65535 | "preferred" | + "alternate". + + `preferred` is converted to priority 1. + `alternate` is converted to priority 2. + + Default value: `"preferred"` + """ + excluded_from_default_policy: bool + """ + When set to `true`, the path-group is excluded from AVD auto generated policies. + + Default value: `False` + """ + dps_keepalive: DpsKeepalive + """ + Period between the transmission of consecutive keepalive messages, and failure threshold. + + Subclass + of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + id: int | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + ipsec: Ipsec | UndefinedType = Undefined, + import_path_groups: ImportPathGroups | UndefinedType = Undefined, + default_preference: str | UndefinedType = Undefined, + excluded_from_default_policy: bool | UndefinedType = Undefined, + dps_keepalive: DpsKeepalive | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + WanPathGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Path-group name. + id: + Path-group id. + Required until an auto ID algorithm is implemented. + description: Additional information about the path-group for documentation purposes. + ipsec: + Configuration of IPSec at the path-group level. + + Subclass of AvdModel. + import_path_groups: + List of path-groups to import in this path-group. + + Subclass of AvdList with `ImportPathGroupsItem` + items. + default_preference: + Preference value used when a preference is not given for a path-group in the + `wan_virtual_topologies.policies` input or when + the path-group is used in an auto generated policy + except if `excluded_from_default_policy` is set to `true. + + Valid values are 1-65535 | "preferred" | + "alternate". + + `preferred` is converted to priority 1. + `alternate` is converted to priority 2. + excluded_from_default_policy: When set to `true`, the path-group is excluded from AVD auto generated policies. + dps_keepalive: + Period between the transmission of consecutive keepalive messages, and failure threshold. + + Subclass + of AvdModel. + _custom_data: _custom_data + + """ + + class WanPathGroups(AvdIndexedList[str, WanPathGroupsItem]): + """Subclass of AvdIndexedList with `WanPathGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + WanPathGroups._item_type = WanPathGroupsItem + + class WanRouteServersItem(AvdModel): + """Subclass of AvdModel.""" + + class PathGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class InterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "public_ip": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Interface name.""" + public_ip: str | None + """The public IPv4 address (without mask) of the Route Reflector for this path-group.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + public_ip: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + InterfacesItem. + + + Subclass of AvdModel. + + Args: + name: Interface name. + public_ip: The public IPv4 address (without mask) of the Route Reflector for this path-group. + _custom_data: _custom_data + + """ + + class Interfaces(AvdIndexedList[str, InterfacesItem]): + """Subclass of AvdIndexedList with `InterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Interfaces._item_type = InterfacesItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "interfaces": {"type": Interfaces}, "_custom_data": {"type": dict}} + name: str + """Path-group name.""" + interfaces: Interfaces + """Subclass of AvdIndexedList with `InterfacesItem` items. Primary key is `name` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + interfaces: Interfaces | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PathGroupsItem. + + + Subclass of AvdModel. + + Args: + name: Path-group name. + interfaces: Subclass of AvdIndexedList with `InterfacesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class PathGroups(AvdIndexedList[str, PathGroupsItem]): + """Subclass of AvdIndexedList with `PathGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PathGroups._item_type = PathGroupsItem + + _fields: ClassVar[dict] = {"hostname": {"type": str}, "vtep_ip": {"type": str}, "path_groups": {"type": PathGroups}, "_custom_data": {"type": dict}} + hostname: str + """Route-Reflector hostname.""" + vtep_ip: str | None + """Route-Reflector VTEP IP Address. This is usually the IP address under `interface Dps1`.""" + path_groups: PathGroups + """ + Path-groups through which the Route Reflector/Pathfinder is reached. + + Subclass of AvdIndexedList + with `PathGroupsItem` items. Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: str | UndefinedType = Undefined, + vtep_ip: str | None | UndefinedType = Undefined, + path_groups: PathGroups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + WanRouteServersItem. + + + Subclass of AvdModel. + + Args: + hostname: Route-Reflector hostname. + vtep_ip: Route-Reflector VTEP IP Address. This is usually the IP address under `interface Dps1`. + path_groups: + Path-groups through which the Route Reflector/Pathfinder is reached. + + Subclass of AvdIndexedList + with `PathGroupsItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class WanRouteServers(AvdIndexedList[str, WanRouteServersItem]): + """Subclass of AvdIndexedList with `WanRouteServersItem` items. Primary key is `hostname` (`str`).""" + + _primary_key: ClassVar[str] = "hostname" + + WanRouteServers._item_type = WanRouteServersItem + + class WanVirtualTopologies(AvdModel): + """Subclass of AvdModel.""" + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "policy": {"type": str, "default": "DEFAULT-POLICY"}, + "wan_vni": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str + """VRF name.""" + policy: str + """ + Name of the policy to apply to this VRF. + AVD will auto generate a default policy DEFAULT-POLICY and + apply it to the VRF(s) + where the `policy` key is not set. + It is possible to overwrite the default + policy for all VRFs using it + by redefining it in the `wan_virtual_topologies.policies` list using + the + default name `DEFAULT-POLICY`. + + Default value: `"DEFAULT-POLICY"` + """ + wan_vni: int + """ + Required for VRFs carried over AutoVPN or CV Pathfinder WAN. + + A VRF can have different VNIs between + the Datacenters and the WAN. + Note that if no VRF default is configured for WAN, AVD will + automatically inject the VRF default with + `wan_vni` set to `1`. + In addition either `vrf_id` or + `vrf_vni` must be set to enforce consistent route-targets across domains. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + policy: str | UndefinedType = Undefined, + wan_vni: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: VRF name. + policy: + Name of the policy to apply to this VRF. + AVD will auto generate a default policy DEFAULT-POLICY and + apply it to the VRF(s) + where the `policy` key is not set. + It is possible to overwrite the default + policy for all VRFs using it + by redefining it in the `wan_virtual_topologies.policies` list using + the + default name `DEFAULT-POLICY`. + wan_vni: + Required for VRFs carried over AutoVPN or CV Pathfinder WAN. + + A VRF can have different VNIs between + the Datacenters and the WAN. + Note that if no VRF default is configured for WAN, AVD will + automatically inject the VRF default with + `wan_vni` set to `1`. + In addition either `vrf_id` or + `vrf_vni` must be set to enforce consistent route-targets across domains. + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + class ControlPlaneVirtualTopology(AvdModel): + """Subclass of AvdModel.""" + + class Constraints(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"jitter": {"type": int}, "latency": {"type": int}, "loss_rate": {"type": str}, "_custom_data": {"type": dict}} + jitter: int | None + """Jitter requirement for this load balance policy in milliseconds.""" + latency: int | None + """One way delay requirement for this load balance policy in milliseconds.""" + loss_rate: str | None + """ + Loss Rate requirement in percentage for this load balance policy. + Value between 0.00 and 100.00. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + jitter: int | None | UndefinedType = Undefined, + latency: int | None | UndefinedType = Undefined, + loss_rate: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Constraints. + + + Subclass of AvdModel. + + Args: + jitter: Jitter requirement for this load balance policy in milliseconds. + latency: One way delay requirement for this load balance policy in milliseconds. + loss_rate: + Loss Rate requirement in percentage for this load balance policy. + Value between 0.00 and 100.00. + _custom_data: _custom_data + + """ + + class PathGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class Names(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Names._item_type = str + + _fields: ClassVar[dict] = {"names": {"type": Names}, "preference": {"type": str}, "_custom_data": {"type": dict}} + names: Names + """ + List of path-group names. + + Subclass of AvdList with `str` items. + """ + preference: str | None + """ + Valid values are 1-65535 | "preferred" | "alternate". + + "preferred" is converted to priority 1. + "alternate" is converted to priority 2. + + If not set, each path-group in `names` will be attributed + its `default_preference`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + names: Names | UndefinedType = Undefined, + preference: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PathGroupsItem. + + + Subclass of AvdModel. + + Args: + names: + List of path-group names. + + Subclass of AvdList with `str` items. + preference: + Valid values are 1-65535 | "preferred" | "alternate". + + "preferred" is converted to priority 1. + "alternate" is converted to priority 2. + + If not set, each path-group in `names` will be attributed + its `default_preference`. + _custom_data: _custom_data + + """ + + class PathGroups(AvdList[PathGroupsItem]): + """Subclass of AvdList with `PathGroupsItem` items.""" + + PathGroups._item_type = PathGroupsItem + + class InternetExit(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"policy": {"type": str}, "_custom_data": {"type": dict}} + policy: str | None + """ + PREVIEW: This key is in preview mode. + + Internet-exit policy name associated with this + virtual_topology. + The policy must be defined under `cv_pathfinder_internet_exit_policies`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, policy: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + InternetExit. + + + Subclass of AvdModel. + + Args: + policy: + PREVIEW: This key is in preview mode. + + Internet-exit policy name associated with this + virtual_topology. + The policy must be defined under `cv_pathfinder_internet_exit_policies`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "application_profile": {"type": str, "default": "APP-PROFILE-CONTROL-PLANE"}, + "traffic_class": {"type": int}, + "dscp": {"type": int}, + "lowest_hop_count": {"type": bool, "default": False}, + "constraints": {"type": Constraints}, + "path_groups": {"type": PathGroups}, + "internet_exit": {"type": InternetExit}, + "_custom_data": {"type": dict}, + } + name: str | None + """Optional name, if not set `CONTROL-PLANE-PROFILE` is used.""" + application_profile: str + """ + The application profile to use for control plane traffic. + + The application profile should be defined + under `application_classification.application_profiles`. + If not defined AVD will auto generate an + application profile using the provided name or the default value. + + If not overwritten elsewhere, the + application profile is generated matching one application matching the control plane traffic either + sourced from or destined to the WAN route servers. + + Default value: `"APP-PROFILE-CONTROL-PLANE"` + """ + traffic_class: int | None + """Set traffic-class for matched traffic.""" + dscp: int | None + """Set DSCP for matched traffic.""" + lowest_hop_count: bool + """ + Prefer paths with lowest hop-count. + Only applicable for `wan_mode: "cv-pathfinder"`. + + Default value: `False` + """ + constraints: Constraints + """Subclass of AvdModel.""" + path_groups: PathGroups + """Subclass of AvdList with `PathGroupsItem` items.""" + internet_exit: InternetExit + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + application_profile: str | UndefinedType = Undefined, + traffic_class: int | None | UndefinedType = Undefined, + dscp: int | None | UndefinedType = Undefined, + lowest_hop_count: bool | UndefinedType = Undefined, + constraints: Constraints | UndefinedType = Undefined, + path_groups: PathGroups | UndefinedType = Undefined, + internet_exit: InternetExit | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ControlPlaneVirtualTopology. + + + Subclass of AvdModel. + + Args: + name: Optional name, if not set `CONTROL-PLANE-PROFILE` is used. + application_profile: + The application profile to use for control plane traffic. + + The application profile should be defined + under `application_classification.application_profiles`. + If not defined AVD will auto generate an + application profile using the provided name or the default value. + + If not overwritten elsewhere, the + application profile is generated matching one application matching the control plane traffic either + sourced from or destined to the WAN route servers. + traffic_class: Set traffic-class for matched traffic. + dscp: Set DSCP for matched traffic. + lowest_hop_count: + Prefer paths with lowest hop-count. + Only applicable for `wan_mode: "cv-pathfinder"`. + constraints: Subclass of AvdModel. + path_groups: Subclass of AvdList with `PathGroupsItem` items. + internet_exit: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class PoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + class ApplicationVirtualTopologiesItem(AvdModel): + """Subclass of AvdModel.""" + + class Constraints(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"jitter": {"type": int}, "latency": {"type": int}, "loss_rate": {"type": str}, "_custom_data": {"type": dict}} + jitter: int | None + """Jitter requirement for this load balance policy in milliseconds.""" + latency: int | None + """One way delay requirement for this load balance policy in milliseconds.""" + loss_rate: str | None + """ + Loss Rate requirement in percentage for this load balance policy. + Value between 0.00 and 100.00. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + jitter: int | None | UndefinedType = Undefined, + latency: int | None | UndefinedType = Undefined, + loss_rate: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Constraints. + + + Subclass of AvdModel. + + Args: + jitter: Jitter requirement for this load balance policy in milliseconds. + latency: One way delay requirement for this load balance policy in milliseconds. + loss_rate: + Loss Rate requirement in percentage for this load balance policy. + Value between 0.00 and 100.00. + _custom_data: _custom_data + + """ + + class PathGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class Names(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Names._item_type = str + + _fields: ClassVar[dict] = {"names": {"type": Names}, "preference": {"type": str}, "_custom_data": {"type": dict}} + names: Names + """ + List of path-group names. + + Subclass of AvdList with `str` items. + """ + preference: str | None + """ + Valid values are 1-65535 | "preferred" | "alternate". + + "preferred" is converted to priority 1. + "alternate" is converted to priority 2. + + If not set, each path-group in `names` will be attributed + its `default_preference`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + names: Names | UndefinedType = Undefined, + preference: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PathGroupsItem. + + + Subclass of AvdModel. + + Args: + names: + List of path-group names. + + Subclass of AvdList with `str` items. + preference: + Valid values are 1-65535 | "preferred" | "alternate". + + "preferred" is converted to priority 1. + "alternate" is converted to priority 2. + + If not set, each path-group in `names` will be attributed + its `default_preference`. + _custom_data: _custom_data + + """ + + class PathGroups(AvdList[PathGroupsItem]): + """Subclass of AvdList with `PathGroupsItem` items.""" + + PathGroups._item_type = PathGroupsItem + + class InternetExit(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"policy": {"type": str}, "_custom_data": {"type": dict}} + policy: str | None + """ + PREVIEW: This key is in preview mode. + + Internet-exit policy name associated with this + virtual_topology. + The policy must be defined under `cv_pathfinder_internet_exit_policies`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, policy: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + InternetExit. + + + Subclass of AvdModel. + + Args: + policy: + PREVIEW: This key is in preview mode. + + Internet-exit policy name associated with this + virtual_topology. + The policy must be defined under `cv_pathfinder_internet_exit_policies`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "application_profile": {"type": str}, + "name": {"type": str}, + "id": {"type": int}, + "traffic_class": {"type": int}, + "dscp": {"type": int}, + "lowest_hop_count": {"type": bool, "default": False}, + "constraints": {"type": Constraints}, + "path_groups": {"type": PathGroups}, + "internet_exit": {"type": InternetExit}, + "_custom_data": {"type": dict}, + } + application_profile: str + """ + The application profile to use for this virtual topology. It must be a defined + `application_classification.application_profile`. + """ + name: str | None + """Optional name, if not set `-` is used.""" + id: int | None + """ + ID of the AVT in each VRFs. ID must be unique across all virtual topologies in a policy. + ID 1 is + reserved for the default_virtual_toplogy. + ID 254 is reserved for the control_plane_virtual_topology. + `id` is required when `wan_mode` is 'cv-pathfinder'. + """ + traffic_class: int | None + """Set traffic-class for matched traffic.""" + dscp: int | None + """Set DSCP for matched traffic.""" + lowest_hop_count: bool + """ + Prefer paths with lowest hop-count. + Only applicable for `wan_mode: "cv-pathfinder"`. + + Default value: `False` + """ + constraints: Constraints + """Subclass of AvdModel.""" + path_groups: PathGroups + """Subclass of AvdList with `PathGroupsItem` items.""" + internet_exit: InternetExit + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + application_profile: str | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + id: int | None | UndefinedType = Undefined, + traffic_class: int | None | UndefinedType = Undefined, + dscp: int | None | UndefinedType = Undefined, + lowest_hop_count: bool | UndefinedType = Undefined, + constraints: Constraints | UndefinedType = Undefined, + path_groups: PathGroups | UndefinedType = Undefined, + internet_exit: InternetExit | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ApplicationVirtualTopologiesItem. + + + Subclass of AvdModel. + + Args: + application_profile: + The application profile to use for this virtual topology. It must be a defined + `application_classification.application_profile`. + name: Optional name, if not set `-` is used. + id: + ID of the AVT in each VRFs. ID must be unique across all virtual topologies in a policy. + ID 1 is + reserved for the default_virtual_toplogy. + ID 254 is reserved for the control_plane_virtual_topology. + `id` is required when `wan_mode` is 'cv-pathfinder'. + traffic_class: Set traffic-class for matched traffic. + dscp: Set DSCP for matched traffic. + lowest_hop_count: + Prefer paths with lowest hop-count. + Only applicable for `wan_mode: "cv-pathfinder"`. + constraints: Subclass of AvdModel. + path_groups: Subclass of AvdList with `PathGroupsItem` items. + internet_exit: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class ApplicationVirtualTopologies(AvdIndexedList[str, ApplicationVirtualTopologiesItem]): + """ + Subclass of AvdIndexedList with `ApplicationVirtualTopologiesItem` items. Primary key is + `application_profile` (`str`). + """ + + _primary_key: ClassVar[str] = "application_profile" + + ApplicationVirtualTopologies._item_type = ApplicationVirtualTopologiesItem + + class DefaultVirtualTopology(AvdModel): + """Subclass of AvdModel.""" + + class Constraints(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"jitter": {"type": int}, "latency": {"type": int}, "loss_rate": {"type": str}, "_custom_data": {"type": dict}} + jitter: int | None + """Jitter requirement for this load balance policy in milliseconds.""" + latency: int | None + """One way delay requirement for this load balance policy in milliseconds.""" + loss_rate: str | None + """ + Loss Rate requirement in percentage for this load balance policy. + Value between 0.00 and 100.00. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + jitter: int | None | UndefinedType = Undefined, + latency: int | None | UndefinedType = Undefined, + loss_rate: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Constraints. + + + Subclass of AvdModel. + + Args: + jitter: Jitter requirement for this load balance policy in milliseconds. + latency: One way delay requirement for this load balance policy in milliseconds. + loss_rate: + Loss Rate requirement in percentage for this load balance policy. + Value between 0.00 and 100.00. + _custom_data: _custom_data + + """ + + class PathGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class Names(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Names._item_type = str + + _fields: ClassVar[dict] = {"names": {"type": Names}, "preference": {"type": str}, "_custom_data": {"type": dict}} + names: Names + """ + List of path-group names. + + Subclass of AvdList with `str` items. + """ + preference: str | None + """ + Valid values are 1-65535 | "preferred" | "alternate". + + "preferred" is converted to priority 1. + "alternate" is converted to priority 2. + + If not set, each path-group in `names` will be attributed + its `default_preference`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + names: Names | UndefinedType = Undefined, + preference: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PathGroupsItem. + + + Subclass of AvdModel. + + Args: + names: + List of path-group names. + + Subclass of AvdList with `str` items. + preference: + Valid values are 1-65535 | "preferred" | "alternate". + + "preferred" is converted to priority 1. + "alternate" is converted to priority 2. + + If not set, each path-group in `names` will be attributed + its `default_preference`. + _custom_data: _custom_data + + """ + + class PathGroups(AvdList[PathGroupsItem]): + """Subclass of AvdList with `PathGroupsItem` items.""" + + PathGroups._item_type = PathGroupsItem + + class InternetExit(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"policy": {"type": str}, "_custom_data": {"type": dict}} + policy: str | None + """ + PREVIEW: This key is in preview mode. + + Internet-exit policy name associated with this + virtual_topology. + The policy must be defined under `cv_pathfinder_internet_exit_policies`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, policy: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + InternetExit. + + + Subclass of AvdModel. + + Args: + policy: + PREVIEW: This key is in preview mode. + + Internet-exit policy name associated with this + virtual_topology. + The policy must be defined under `cv_pathfinder_internet_exit_policies`. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "drop_unmatched": {"type": bool, "default": False}, + "traffic_class": {"type": int}, + "dscp": {"type": int}, + "lowest_hop_count": {"type": bool, "default": False}, + "constraints": {"type": Constraints}, + "path_groups": {"type": PathGroups}, + "internet_exit": {"type": InternetExit}, + "_custom_data": {"type": dict}, + } + name: str | None + """Optional name, if not set `-DEFAULT` is used.""" + drop_unmatched: bool + """ + When set, no `catch-all` match is configured for the policy and unmatched traffic is dropped. + + Default value: `False` + """ + traffic_class: int | None + """Set traffic-class for matched traffic.""" + dscp: int | None + """Set DSCP for matched traffic.""" + lowest_hop_count: bool + """ + Prefer paths with lowest hop-count. + Only applicable for `wan_mode: "cv-pathfinder"`. + + Default value: `False` + """ + constraints: Constraints + """Subclass of AvdModel.""" + path_groups: PathGroups + """Subclass of AvdList with `PathGroupsItem` items.""" + internet_exit: InternetExit + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + drop_unmatched: bool | UndefinedType = Undefined, + traffic_class: int | None | UndefinedType = Undefined, + dscp: int | None | UndefinedType = Undefined, + lowest_hop_count: bool | UndefinedType = Undefined, + constraints: Constraints | UndefinedType = Undefined, + path_groups: PathGroups | UndefinedType = Undefined, + internet_exit: InternetExit | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultVirtualTopology. + + + Subclass of AvdModel. + + Args: + name: Optional name, if not set `-DEFAULT` is used. + drop_unmatched: When set, no `catch-all` match is configured for the policy and unmatched traffic is dropped. + traffic_class: Set traffic-class for matched traffic. + dscp: Set DSCP for matched traffic. + lowest_hop_count: + Prefer paths with lowest hop-count. + Only applicable for `wan_mode: "cv-pathfinder"`. + constraints: Subclass of AvdModel. + path_groups: Subclass of AvdList with `PathGroupsItem` items. + internet_exit: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "application_virtual_topologies": {"type": ApplicationVirtualTopologies}, + "default_virtual_topology": {"type": DefaultVirtualTopology}, + "_custom_data": {"type": dict}, + } + name: str + """Name of the AVT policy.""" + application_virtual_topologies: ApplicationVirtualTopologies + """ + List of application specific virtual topologies. + + Subclass of AvdIndexedList with + `ApplicationVirtualTopologiesItem` items. Primary key is `application_profile` (`str`). + """ + default_virtual_topology: DefaultVirtualTopology + """ + Default match for the policy. + If no default match should be configured, set `drop_unmatched` to + `true`. + Otherwise, in CV Pathfinder mode, a default AVT profile will be configured with ID 1. + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + application_virtual_topologies: ApplicationVirtualTopologies | UndefinedType = Undefined, + default_virtual_topology: DefaultVirtualTopology | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PoliciesItem. + + + Subclass of AvdModel. + + Args: + name: Name of the AVT policy. + application_virtual_topologies: + List of application specific virtual topologies. + + Subclass of AvdIndexedList with + `ApplicationVirtualTopologiesItem` items. Primary key is `application_profile` (`str`). + default_virtual_topology: + Default match for the policy. + If no default match should be configured, set `drop_unmatched` to + `true`. + Otherwise, in CV Pathfinder mode, a default AVT profile will be configured with ID 1. + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Policies(AvdIndexedList[str, PoliciesItem]): + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Policies._item_type = PoliciesItem + + _fields: ClassVar[dict] = { + "vrfs": {"type": Vrfs}, + "control_plane_virtual_topology": {"type": ControlPlaneVirtualTopology}, + "policies": {"type": Policies}, + "_custom_data": {"type": dict}, + } + vrfs: Vrfs + """ + Map a VRF that exists in network_services to an AVT policy. + + Subclass of AvdIndexedList with + `VrfsItem` items. Primary key is `name` (`str`). + """ + control_plane_virtual_topology: ControlPlaneVirtualTopology + """ + Always injected into the default VRF policy as the first entry. + + By default, if no path-groups are + specified, all locally available path-groups + are used in the generated load-balance policy. + ID is + hardcoded to 254 for the AVT profile in CV Pathfinder mode. + + Subclass of AvdModel. + """ + policies: Policies + """ + List of virtual topologies policies. + + For AutoVPN, each item in the list creates: + * one policy + with: + * one `match` entry per `application_virtual_topologies` item + they are indexed + using `10 * ` where `list_index` starts at `1`. + * one `default-match` + * one + load-balance policy per `application_virtual_topologies` and one for the `default_virtual_topology`. + * if the policy is associated with the default VRF, a special control-plane rule is injected + in + the policy with index `1` referring to a control-plane load-balance policy as defined under + `control_plane_virtual_topology` or if not set, the default one. + + For CV Pathfinder, each item in + the list creates: + * one policy with: + * one `match` entry per + `application_virtual_topologies` item ordered as in the data. + * one last match entry for the + `default` application-profile using `default_virtual_topology` information. + * one profile per + `application_virtual_topologies` item. + * one profile for the `default_virtual_topology`. + * one + load-balance policy per `application_virtual_topologies`. + * one load_balance policy for the + `default_virtual_topology`. + * if the policy is associated with the default VRF, a special control- + plane profile is configured + and injected first in the policy assigned to the `default` VRF. This + profile points to a + control-plane load-balance policy as defined under + `control_plane_virtual_topology` or if not set, the default one. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + vrfs: Vrfs | UndefinedType = Undefined, + control_plane_virtual_topology: ControlPlaneVirtualTopology | UndefinedType = Undefined, + policies: Policies | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + WanVirtualTopologies. + + + Subclass of AvdModel. + + Args: + vrfs: + Map a VRF that exists in network_services to an AVT policy. + + Subclass of AvdIndexedList with + `VrfsItem` items. Primary key is `name` (`str`). + control_plane_virtual_topology: + Always injected into the default VRF policy as the first entry. + + By default, if no path-groups are + specified, all locally available path-groups + are used in the generated load-balance policy. + ID is + hardcoded to 254 for the AVT profile in CV Pathfinder mode. + + Subclass of AvdModel. + policies: + List of virtual topologies policies. + + For AutoVPN, each item in the list creates: + * one policy + with: + * one `match` entry per `application_virtual_topologies` item + they are indexed + using `10 * ` where `list_index` starts at `1`. + * one `default-match` + * one + load-balance policy per `application_virtual_topologies` and one for the `default_virtual_topology`. + * if the policy is associated with the default VRF, a special control-plane rule is injected + in + the policy with index `1` referring to a control-plane load-balance policy as defined under + `control_plane_virtual_topology` or if not set, the default one. + + For CV Pathfinder, each item in + the list creates: + * one policy with: + * one `match` entry per + `application_virtual_topologies` item ordered as in the data. + * one last match entry for the + `default` application-profile using `default_virtual_topology` information. + * one profile per + `application_virtual_topologies` item. + * one profile for the `default_virtual_topology`. + * one + load-balance policy per `application_virtual_topologies`. + * one load_balance policy for the + `default_virtual_topology`. + * if the policy is associated with the default VRF, a special control- + plane profile is configured + and injected first in the policy assigned to the `default` VRF. This + profile points to a + control-plane load-balance policy as defined under + `control_plane_virtual_topology` or if not set, the default one. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class ZscalerEndpoints(AvdModel): + """Subclass of AvdModel.""" + + class Primary(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "datacenter": {"type": str}, + "city": {"type": str}, + "country": {"type": str}, + "region": {"type": str}, + "latitude": {"type": str}, + "longitude": {"type": str}, + "_custom_data": {"type": dict}, + } + ip_address: str + datacenter: str + city: str + country: str + region: str + latitude: str + longitude: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + datacenter: str | UndefinedType = Undefined, + city: str | UndefinedType = Undefined, + country: str | UndefinedType = Undefined, + region: str | UndefinedType = Undefined, + latitude: str | UndefinedType = Undefined, + longitude: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Primary. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + datacenter: datacenter + city: city + country: country + region: region + latitude: latitude + longitude: longitude + _custom_data: _custom_data + + """ + + class Secondary(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "datacenter": {"type": str}, + "city": {"type": str}, + "country": {"type": str}, + "region": {"type": str}, + "latitude": {"type": str}, + "longitude": {"type": str}, + "_custom_data": {"type": dict}, + } + ip_address: str + datacenter: str + city: str + country: str + region: str + latitude: str + longitude: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + datacenter: str | UndefinedType = Undefined, + city: str | UndefinedType = Undefined, + country: str | UndefinedType = Undefined, + region: str | UndefinedType = Undefined, + latitude: str | UndefinedType = Undefined, + longitude: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Secondary. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + datacenter: datacenter + city: city + country: country + region: region + latitude: latitude + longitude: longitude + _custom_data: _custom_data + + """ + + class Tertiary(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "datacenter": {"type": str}, + "city": {"type": str}, + "country": {"type": str}, + "region": {"type": str}, + "latitude": {"type": str}, + "longitude": {"type": str}, + "_custom_data": {"type": dict}, + } + ip_address: str + datacenter: str + city: str + country: str + region: str + latitude: str + longitude: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + datacenter: str | UndefinedType = Undefined, + city: str | UndefinedType = Undefined, + country: str | UndefinedType = Undefined, + region: str | UndefinedType = Undefined, + latitude: str | UndefinedType = Undefined, + longitude: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Tertiary. + + + Subclass of AvdModel. + + Args: + ip_address: ip_address + datacenter: datacenter + city: city + country: country + region: region + latitude: latitude + longitude: longitude + _custom_data: _custom_data + + """ + + class DeviceLocation(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"city": {"type": str}, "country": {"type": str}, "_custom_data": {"type": dict}} + city: str + country: str + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + city: str | UndefinedType = Undefined, + country: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DeviceLocation. + + + Subclass of AvdModel. + + Args: + city: city + country: country + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "primary": {"type": Primary}, + "secondary": {"type": Secondary}, + "tertiary": {"type": Tertiary}, + "cloud_name": {"type": str}, + "device_location": {"type": DeviceLocation}, + "_custom_data": {"type": dict}, + } + primary: Primary + """Subclass of AvdModel.""" + secondary: Secondary + """Subclass of AvdModel.""" + tertiary: Tertiary + """Subclass of AvdModel.""" + cloud_name: str + """ + The name of the Zscaler cloud the CloudVision cluster is integrated with like 'zscaler1' or + 'zscalerbeta'. + """ + device_location: DeviceLocation + """ + The location of the calling device after being resolved by Zscaler location APIs. This is required + since Zscaler only accepts their own variants of City and Country. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + primary: Primary | UndefinedType = Undefined, + secondary: Secondary | UndefinedType = Undefined, + tertiary: Tertiary | UndefinedType = Undefined, + cloud_name: str | UndefinedType = Undefined, + device_location: DeviceLocation | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ZscalerEndpoints. + + + Subclass of AvdModel. + + Args: + primary: Subclass of AvdModel. + secondary: Subclass of AvdModel. + tertiary: Subclass of AvdModel. + cloud_name: + The name of the Zscaler cloud the CloudVision cluster is integrated with like 'zscaler1' or + 'zscalerbeta'. + device_location: + The location of the calling device after being resolved by Zscaler location APIs. This is required + since Zscaler only accepts their own variants of City and Country. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class _CustomStructuredConfigurationsItem(AvdModel): + _fields: ClassVar[dict] = {"key": {"type": str}, "value": {"type": EosCliConfigGen}} + key: str + """Complete key including prefix""" + value: EosCliConfigGen + """Structured config including the suffix part of the key.""" + + if TYPE_CHECKING: + + def __init__(self, *, key: str | UndefinedType = Undefined, value: EosCliConfigGen | UndefinedType = Undefined) -> None: + """ + _CustomStructuredConfigurationsItem. + + + Args: + key: Complete key including prefix + value: Structured config including the suffix part of the key. + + """ + + class _CustomStructuredConfigurations(AvdIndexedList[str, _CustomStructuredConfigurationsItem]): + _primary_key: ClassVar[str] = "key" + + _CustomStructuredConfigurations._item_type = _CustomStructuredConfigurationsItem + + class _DynamicKeys(AvdModel): + """Data models for dynamic keys.""" + + class DynamicConnectedEndpointsItem(AvdModel): + class ConnectedEndpointsItem(AvdModel): + """Subclass of AvdModel.""" + + class AdaptersItem(AvdModel): + """Subclass of AvdModel.""" + + class SwitchPorts(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + SwitchPorts._item_type = str + + class Switches(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Switches._item_type = str + + class EndpointPorts(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + EndpointPorts._item_type = str + + class Descriptions(AvdList[Any]): + """Subclass of AvdList with `Any` items.""" + + Descriptions._item_type = Any + + class TrunkGroups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + TrunkGroups._item_type = str + + class Flowcontrol(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"received": {"type": str}, "_custom_data": {"type": dict}} + received: Literal["received", "send", "on"] | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + received: Literal["received", "send", "on"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Flowcontrol. + + + Subclass of AvdModel. + + Args: + received: received + _custom_data: _custom_data + + """ + + class Ptp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "endpoint_role": {"type": str, "default": "follower"}, + "profile": {"type": str, "default": "aes67-r16-2016"}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + endpoint_role: Literal["bmca", "default", "follower"] + """Default value: `"follower"`""" + profile: str + """ + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + + Default value: `"aes67-r16-2016"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + endpoint_role: Literal["bmca", "default", "follower"] | UndefinedType = Undefined, + profile: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ptp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + endpoint_role: endpoint_role + profile: + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + _custom_data: _custom_data + + """ + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class LinkTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """ + Tracking group name. + The default group name is taken from fabric variable of the switch, + `link_tracking.groups[0].name` with default value being "LT_GROUP1". + Optional if default + link_tracking settings are configured on the node. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: + Tracking group name. + The default group name is taken from fabric variable of the switch, + `link_tracking.groups[0].name` with default value being "LT_GROUP1". + Optional if default + link_tracking settings are configured on the node. + _custom_data: _custom_data + + """ + + class Dot1x(EosCliConfigGen.EthernetInterfacesItem.Dot1x): + """Subclass of AvdModel.""" + + class Poe(EosCliConfigGen.EthernetInterfacesItem.Poe): + """Subclass of AvdModel.""" + + class StormControl(AvdModel): + """Subclass of AvdModel.""" + + class All(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional variable and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + All. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional variable and is hardware dependent. + _custom_data: _custom_data + + """ + + class Broadcast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional variable and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Broadcast. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional variable and is hardware dependent. + _custom_data: _custom_data + + """ + + class Multicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional variable and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Multicast. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional variable and is hardware dependent. + _custom_data: _custom_data + + """ + + class UnknownUnicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"level": {"type": str}, "unit": {"type": str, "default": "percent"}, "_custom_data": {"type": dict}} + level: str | None + """Configure maximum storm-control level.""" + unit: Literal["percent", "pps"] + """ + Optional variable and is hardware dependent. + + Default value: `"percent"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + level: str | None | UndefinedType = Undefined, + unit: Literal["percent", "pps"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + UnknownUnicast. + + + Subclass of AvdModel. + + Args: + level: Configure maximum storm-control level. + unit: Optional variable and is hardware dependent. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "all": {"type": All}, + "broadcast": {"type": Broadcast}, + "multicast": {"type": Multicast}, + "unknown_unicast": {"type": UnknownUnicast}, + "_custom_data": {"type": dict}, + } + all: All + """Subclass of AvdModel.""" + broadcast: Broadcast + """Subclass of AvdModel.""" + multicast: Multicast + """Subclass of AvdModel.""" + unknown_unicast: UnknownUnicast + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + all: All | UndefinedType = Undefined, + broadcast: Broadcast | UndefinedType = Undefined, + multicast: Multicast | UndefinedType = Undefined, + unknown_unicast: UnknownUnicast | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StormControl. + + + Subclass of AvdModel. + + Args: + all: Subclass of AvdModel. + broadcast: Subclass of AvdModel. + multicast: Subclass of AvdModel. + unknown_unicast: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MonitorSessionsItem(AvdModel): + """Subclass of AvdModel.""" + + class SourceSettings(AvdModel): + """Subclass of AvdModel.""" + + class AccessGroup(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "type": {"type": str}, + "name": {"type": str}, + "priority": {"type": int}, + "_custom_data": {"type": dict}, + } + type: Literal["ip", "ipv6", "mac"] | None + name: str | None + """ACL name.""" + priority: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + type: Literal["ip", "ipv6", "mac"] | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + priority: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AccessGroup. + + + Subclass of AvdModel. + + Args: + type: type + name: ACL name. + priority: priority + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"direction": {"type": str}, "access_group": {"type": AccessGroup}, "_custom_data": {"type": dict}} + direction: Literal["rx", "tx", "both"] | None + access_group: AccessGroup + """ + This can only be set when `session_settings.access_group` is not set. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction: Literal["rx", "tx", "both"] | None | UndefinedType = Undefined, + access_group: AccessGroup | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SourceSettings. + + + Subclass of AvdModel. + + Args: + direction: direction + access_group: + This can only be set when `session_settings.access_group` is not set. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class SessionSettings(AvdModel): + """Subclass of AvdModel.""" + + class AccessGroup(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"type": {"type": str}, "name": {"type": str}, "_custom_data": {"type": dict}} + type: Literal["ip", "ipv6", "mac"] | None + name: str | None + """ACL name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + type: Literal["ip", "ipv6", "mac"] | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AccessGroup. + + + Subclass of AvdModel. + + Args: + type: type + name: ACL name. + _custom_data: _custom_data + + """ + + class Truncate(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "size": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool | None + size: int | None + """Size in bytes.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + size: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Truncate. + + + Subclass of AvdModel. + + Args: + enabled: enabled + size: Size in bytes. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "encapsulation_gre_metadata_tx": {"type": bool}, + "header_remove_size": {"type": int}, + "access_group": {"type": AccessGroup}, + "rate_limit_per_ingress_chip": {"type": str}, + "rate_limit_per_egress_chip": {"type": str}, + "sample": {"type": int}, + "truncate": {"type": Truncate}, + "_custom_data": {"type": dict}, + } + encapsulation_gre_metadata_tx: bool | None + header_remove_size: int | None + """Number of bytes to remove from header.""" + access_group: AccessGroup + """Subclass of AvdModel.""" + rate_limit_per_ingress_chip: str | None + """ + Ratelimit and unit as string. + Examples: + "100000 bps" + "100 kbps" + "10 mbps" + """ + rate_limit_per_egress_chip: str | None + """ + Ratelimit and unit as string. + Examples: + "100000 bps" + "100 kbps" + "10 mbps" + """ + sample: int | None + truncate: Truncate + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + encapsulation_gre_metadata_tx: bool | None | UndefinedType = Undefined, + header_remove_size: int | None | UndefinedType = Undefined, + access_group: AccessGroup | UndefinedType = Undefined, + rate_limit_per_ingress_chip: str | None | UndefinedType = Undefined, + rate_limit_per_egress_chip: str | None | UndefinedType = Undefined, + sample: int | None | UndefinedType = Undefined, + truncate: Truncate | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SessionSettings. + + + Subclass of AvdModel. + + Args: + encapsulation_gre_metadata_tx: encapsulation_gre_metadata_tx + header_remove_size: Number of bytes to remove from header. + access_group: Subclass of AvdModel. + rate_limit_per_ingress_chip: + Ratelimit and unit as string. + Examples: # fmt: skip + "100000 bps" + "100 kbps" + "10 mbps" + rate_limit_per_egress_chip: + Ratelimit and unit as string. + Examples: # fmt: skip + "100000 bps" + "100 kbps" + "10 mbps" + sample: sample + truncate: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "role": {"type": str}, + "source_settings": {"type": SourceSettings}, + "session_settings": {"type": SessionSettings}, + "_custom_data": {"type": dict}, + } + name: str + """Session name.""" + role: Literal["source", "destination"] | None + source_settings: SourceSettings + """Subclass of AvdModel.""" + session_settings: SessionSettings + """ + Session settings are defined per session name. + Different session_settings for the same session name + will be combined/merged. + + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + role: Literal["source", "destination"] | None | UndefinedType = Undefined, + source_settings: SourceSettings | UndefinedType = Undefined, + session_settings: SessionSettings | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MonitorSessionsItem. + + + Subclass of AvdModel. + + Args: + name: Session name. + role: role + source_settings: Subclass of AvdModel. + session_settings: + Session settings are defined per session name. + Different session_settings for the same session name + will be combined/merged. + + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MonitorSessions(AvdList[MonitorSessionsItem]): + """Subclass of AvdList with `MonitorSessionsItem` items.""" + + MonitorSessions._item_type = MonitorSessionsItem + + class EthernetSegment(AvdModel): + """Subclass of AvdModel.""" + + class DesignatedForwarderPreferences(AvdList[int]): + """Subclass of AvdList with `int` items.""" + + DesignatedForwarderPreferences._item_type = int + + _fields: ClassVar[dict] = { + "short_esi": {"type": str}, + "redundancy": {"type": str}, + "designated_forwarder_algorithm": {"type": str}, + "designated_forwarder_preferences": {"type": DesignatedForwarderPreferences}, + "dont_preempt": {"type": bool}, + "_custom_data": {"type": dict}, + } + short_esi: str + """ + In format xxxx:xxxx:xxxx or "auto". + Define a manual short-esi (be careful using this on profiles) or + set the value to "auto" to automatically generate the value. + Please see the notes under "EVPN A/A + ESI dual and single-attached endpoint scenarios" before setting `short_esi: auto`. + """ + redundancy: Literal["all-active", "single-active"] | None + """ + If omitted, Port-Channels use the EOS default of all-active. + If omitted, Ethernet interfaces are + configured as single-active. + """ + designated_forwarder_algorithm: Literal["auto", "modulus", "preference"] | None + """ + Configure DF algorithm and preferences. + - auto: Use preference-based algorithm and assign preference + based on position of device in the 'switches' list, + e.g., assuming a list of three switches, this + would assign a preference of 200 to the first switch, 100 to the 2nd, and 0 to the third. + - + preference: Set preference for each switch manually using designated_forwarder_preferences key. + - + modulus: Use the default modulus-based algorithm. + If omitted, Port-Channels use the EOS default of + modulus. + If omitted, Ethernet interfaces default to the 'auto' mechanism detailed above. + """ + designated_forwarder_preferences: DesignatedForwarderPreferences + """ + Manual preference as described above, required only for preference algorithm. + + Subclass of AvdList + with `int` items. + """ + dont_preempt: bool | None + """Disable preemption for single-active forwarding when auto/manual DF preference is configured.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + short_esi: str | UndefinedType = Undefined, + redundancy: Literal["all-active", "single-active"] | None | UndefinedType = Undefined, + designated_forwarder_algorithm: Literal["auto", "modulus", "preference"] | None | UndefinedType = Undefined, + designated_forwarder_preferences: DesignatedForwarderPreferences | UndefinedType = Undefined, + dont_preempt: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EthernetSegment. + + + Subclass of AvdModel. + + Args: + short_esi: + In format xxxx:xxxx:xxxx or "auto". + Define a manual short-esi (be careful using this on profiles) or + set the value to "auto" to automatically generate the value. + Please see the notes under "EVPN A/A + ESI dual and single-attached endpoint scenarios" before setting `short_esi: auto`. + redundancy: + If omitted, Port-Channels use the EOS default of all-active. + If omitted, Ethernet interfaces are + configured as single-active. + designated_forwarder_algorithm: + Configure DF algorithm and preferences. + - auto: Use preference-based algorithm and assign preference + based on position of device in the 'switches' list, + e.g., assuming a list of three switches, this + would assign a preference of 200 to the first switch, 100 to the 2nd, and 0 to the third. + - + preference: Set preference for each switch manually using designated_forwarder_preferences key. + - + modulus: Use the default modulus-based algorithm. + If omitted, Port-Channels use the EOS default of + modulus. + If omitted, Ethernet interfaces default to the 'auto' mechanism detailed above. + designated_forwarder_preferences: + Manual preference as described above, required only for preference algorithm. + + Subclass of AvdList + with `int` items. + dont_preempt: Disable preemption for single-active forwarding when auto/manual DF preference is configured. + _custom_data: _custom_data + + """ + + class PortChannel(AvdModel): + """Subclass of AvdModel.""" + + class LacpFallback(AvdModel): + """Subclass of AvdModel.""" + + class Individual(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "_custom_data": {"type": dict}} + profile: str | None + """Port-profile name to inherit configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, profile: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Individual. + + + Subclass of AvdModel. + + Args: + profile: Port-profile name to inherit configuration. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "mode": {"type": str}, + "individual": {"type": Individual}, + "timeout": {"type": int}, + "_custom_data": {"type": dict}, + } + mode: Literal["static", "individual"] | None + """ + Either static or individual mode is supported. + If the mode is set to "individual" the + "individual.profile" setting must be defined. + """ + individual: Individual + """ + Define parameters for port-channel member interfaces. Applies only if LACP fallback is set to + "individual". + + Subclass of AvdModel. + """ + timeout: int | None + """Timeout in seconds. EOS default is 90 seconds.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["static", "individual"] | None | UndefinedType = Undefined, + individual: Individual | UndefinedType = Undefined, + timeout: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LacpFallback. + + + Subclass of AvdModel. + + Args: + mode: + Either static or individual mode is supported. + If the mode is set to "individual" the + "individual.profile" setting must be defined. + individual: + Define parameters for port-channel member interfaces. Applies only if LACP fallback is set to + "individual". + + Subclass of AvdModel. + timeout: Timeout in seconds. EOS default is 90 seconds. + _custom_data: _custom_data + + """ + + class LacpTimer(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"mode": {"type": str}, "multiplier": {"type": int}, "_custom_data": {"type": dict}} + mode: Literal["normal", "fast"] | None + """LACP mode for interface members.""" + multiplier: int | None + """Number of LACP BPDUs lost before deeming the peer down. EOS default is 3.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["normal", "fast"] | None | UndefinedType = Undefined, + multiplier: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LacpTimer. + + + Subclass of AvdModel. + + Args: + mode: LACP mode for interface members. + multiplier: Number of LACP BPDUs lost before deeming the peer down. EOS default is 3. + _custom_data: _custom_data + + """ + + class SubinterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class EncapsulationVlan(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"client_dot1q": {"type": int}, "_custom_data": {"type": dict}} + client_dot1q: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, client_dot1q: int | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + EncapsulationVlan. + + + Subclass of AvdModel. + + Args: + client_dot1q: client_dot1q + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "number": {"type": int}, + "short_esi": {"type": str}, + "vlan_id": {"type": int}, + "encapsulation_vlan": {"type": EncapsulationVlan}, + "_custom_data": {"type": dict}, + } + number: int | None + """Subinterface number.""" + short_esi: str | None + """ + In format xxxx:xxxx:xxxx or "auto". + Required for multihomed port-channels with subinterfaces. + """ + vlan_id: int | None + """ + VLAN ID to bridge. + Default is subinterface number. + """ + encapsulation_vlan: EncapsulationVlan + """ + Client VLAN ID encapsulation. + Default is subinterface number. + + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + number: int | None | UndefinedType = Undefined, + short_esi: str | None | UndefinedType = Undefined, + vlan_id: int | None | UndefinedType = Undefined, + encapsulation_vlan: EncapsulationVlan | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SubinterfacesItem. + + + Subclass of AvdModel. + + Args: + number: Subinterface number. + short_esi: + In format xxxx:xxxx:xxxx or "auto". + Required for multihomed port-channels with subinterfaces. + vlan_id: + VLAN ID to bridge. + Default is subinterface number. + encapsulation_vlan: + Client VLAN ID encapsulation. + Default is subinterface number. + + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Subinterfaces(AvdList[SubinterfacesItem]): + """Subclass of AvdList with `SubinterfacesItem` items.""" + + Subinterfaces._item_type = SubinterfacesItem + + class StructuredConfig(EosCliConfigGen.PortChannelInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "mode": {"type": str}, + "channel_id": {"type": int}, + "description": {"type": str}, + "endpoint_port_channel": {"type": str}, + "enabled": {"type": bool, "default": True}, + "ptp_mpass": {"type": bool, "default": False}, + "lacp_fallback": {"type": LacpFallback}, + "lacp_timer": {"type": LacpTimer}, + "subinterfaces": {"type": Subinterfaces}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + mode: Literal["active", "passive", "on"] | None + """Port-Channel Mode.""" + channel_id: int | None + """ + Port-Channel ID. + If no channel_id is specified, an id is generated from the first switch port in the + port channel. + """ + description: str | None + """ + Description or description template to be used on the port-channel interface. + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `endpoint_type` - the `type` from `connected_endpoints_keys` like `server`, `router` etc. + - + `endpoint` - The name of the connected endpoint + - `endpoint_port_channel` - The value from + `endpoint_port_channel` if set. + - `port_channel_id` - The port-channel number for the switch. + - + `adapter_description` - The adapter's description if set. + - `adapter_description_or_endpoint` - + Helper alias of the adapter_description or endpoint. + + The default description is set by + `default_connected_endpoints_port_channel_description`. + By default the description is templated from + the type, name and port_channel interface of the endpoint if set. + """ + endpoint_port_channel: str | None + """ + Name of the port-channel interface on the endpoint. + Used for the port-channel description template + with the field name `peer_interface` + """ + enabled: bool + """ + Port-Channel administrative state. + Setting to false will set port to 'shutdown' in intended + configuration. + + Default value: `True` + """ + ptp_mpass: bool + """ + When MPASS is enabled on an MLAG port-channel, MLAG peers coordinate to function as a single PTP + logical device. + Arista PTP enabled devices always place PTP messages on the same physical link + within the port-channel. + Hence, MPASS is needed only on MLAG port-channels connected to non-Arista + devices. + + Default value: `False` + """ + lacp_fallback: LacpFallback + """ + LACP fallback configuration. + + Subclass of AvdModel. + """ + lacp_timer: LacpTimer + """ + LACP timer configuration. Applies only when Port-channel mode is not "on". + + Subclass of AvdModel. + """ + subinterfaces: Subinterfaces + """ + Port-Channel L2 Subinterfaces + Subinterfaces are only supported on routed port-channels, which means + they cannot be configured on MLAG port-channels. + Setting short_esi: auto generates the short_esi + automatically using a hash of configuration elements. + Please see the notes under "EVPN A/A ESI dual- + attached endpoint scenario" before setting short_esi: auto. + + + Subclass of AvdList with + `SubinterfacesItem` items. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the port-channel interface in the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["active", "passive", "on"] | None | UndefinedType = Undefined, + channel_id: int | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + endpoint_port_channel: str | None | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + ptp_mpass: bool | UndefinedType = Undefined, + lacp_fallback: LacpFallback | UndefinedType = Undefined, + lacp_timer: LacpTimer | UndefinedType = Undefined, + subinterfaces: Subinterfaces | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PortChannel. + + + Subclass of AvdModel. + + Args: + mode: Port-Channel Mode. + channel_id: + Port-Channel ID. + If no channel_id is specified, an id is generated from the first switch port in the + port channel. + description: + Description or description template to be used on the port-channel interface. + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `endpoint_type` - the `type` from `connected_endpoints_keys` like `server`, `router` etc. + - + `endpoint` - The name of the connected endpoint + - `endpoint_port_channel` - The value from + `endpoint_port_channel` if set. + - `port_channel_id` - The port-channel number for the switch. + - + `adapter_description` - The adapter's description if set. + - `adapter_description_or_endpoint` - + Helper alias of the adapter_description or endpoint. + + The default description is set by + `default_connected_endpoints_port_channel_description`. + By default the description is templated from + the type, name and port_channel interface of the endpoint if set. + endpoint_port_channel: + Name of the port-channel interface on the endpoint. + Used for the port-channel description template + with the field name `peer_interface` + enabled: + Port-Channel administrative state. + Setting to false will set port to 'shutdown' in intended + configuration. + ptp_mpass: + When MPASS is enabled on an MLAG port-channel, MLAG peers coordinate to function as a single PTP + logical device. + Arista PTP enabled devices always place PTP messages on the same physical link + within the port-channel. + Hence, MPASS is needed only on MLAG port-channels connected to non-Arista + devices. + lacp_fallback: + LACP fallback configuration. + + Subclass of AvdModel. + lacp_timer: + LACP timer configuration. Applies only when Port-channel mode is not "on". + + Subclass of AvdModel. + subinterfaces: + Port-Channel L2 Subinterfaces + Subinterfaces are only supported on routed port-channels, which means + they cannot be configured on MLAG port-channels. + Setting short_esi: auto generates the short_esi + automatically using a hash of configuration elements. + Please see the notes under "EVPN A/A ESI dual- + attached endpoint scenario" before setting short_esi: auto. + + + Subclass of AvdList with + `SubinterfacesItem` items. + raw_eos_cli: EOS CLI rendered directly on the port-channel interface in the final EOS configuration. + structured_config: + Custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "switch_ports": {"type": SwitchPorts}, + "switches": {"type": Switches}, + "endpoint_ports": {"type": EndpointPorts}, + "descriptions": {"type": Descriptions}, + "speed": {"type": str}, + "description": {"type": str}, + "profile": {"type": str}, + "enabled": {"type": bool, "default": True}, + "mode": {"type": str}, + "mtu": {"type": int}, + "l2_mtu": {"type": int}, + "l2_mru": {"type": int}, + "native_vlan": {"type": int}, + "native_vlan_tag": {"type": bool}, + "phone_vlan": {"type": int}, + "phone_trunk_mode": {"type": str}, + "trunk_groups": {"type": TrunkGroups}, + "vlans": {"type": str}, + "spanning_tree_portfast": {"type": str}, + "spanning_tree_bpdufilter": {"type": str}, + "spanning_tree_bpduguard": {"type": str}, + "flowcontrol": {"type": Flowcontrol}, + "qos_profile": {"type": str}, + "ptp": {"type": Ptp}, + "sflow": {"type": bool}, + "flow_tracking": {"type": FlowTracking}, + "link_tracking": {"type": LinkTracking}, + "dot1x": {"type": Dot1x}, + "poe": {"type": Poe}, + "storm_control": {"type": StormControl}, + "monitor_sessions": {"type": MonitorSessions}, + "ethernet_segment": {"type": EthernetSegment}, + "port_channel": {"type": PortChannel}, + "validate_state": {"type": bool}, + "validate_lldp": {"type": bool}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + switch_ports: SwitchPorts + """ + List of switch interfaces. + The lists `endpoint_ports`, `switch_ports`, and `switches` must have the + same length. + + + Subclass of AvdList with `str` items. + """ + switches: Switches + """ + List of switches. + The lists `endpoint_ports`, `switch_ports`, and `switches` must have the same + length. + + + Subclass of AvdList with `str` items. + """ + endpoint_ports: EndpointPorts + """ + Endpoint ports is used for description, required unless `description` or `descriptions` is set. + The + lists `endpoint_ports`, `switch_ports`, `descriptions` and `switches` must have the same length. + Each list item is one switchport. + + + Subclass of AvdList with `str` items. + """ + descriptions: Descriptions + """ + Unique description per port. When set, takes priority over description. + This can be a template using + the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom- + descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - + `endpoint_type` - the `type` from `connected_endpoints_keys` like `server`, `router` etc. + - + `endpoint` - The name of the connected endpoint + - `endpoint_port` - The value from + `endpoint_ports` for this switch port if set. + - `port_channel_id`: The port-channel number for the + switch. + + Subclass of AvdList with `Any` items. + """ + speed: str | None + """ + Set adapter speed in the format `` or `forced ` or `auto + `. + If not specified speed will be auto. + """ + description: str | None + """ + Description or description template to be used on all ports. + This can be a template using the AVD + string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom- + descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - + `endpoint_type` - the `type` from `connected_endpoints_keys` like `server`, `router` etc. + - + `endpoint` - The name of the connected endpoint + - `endpoint_port` - The value from + `endpoint_ports` for this switch port if set. + + The default description is set by + `default_connected_endpoints_description`. + By default the description is templated from the type, + name and port of the endpoint if set. + """ + profile: str | None + """Port-profile name to inherit configuration.""" + enabled: bool + """ + Administrative state, setting to false will set the port to 'shutdown' in the intended + configuration. + + Default value: `True` + """ + mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None + """Interface mode.""" + mtu: int | None + l2_mtu: int | None + """"l2_mtu" should only be defined for platforms supporting the "l2 mtu" CLI.""" + l2_mru: int | None + """"l2_mru" should only be defined for platforms supporting the "l2 mru" CLI.""" + native_vlan: int | None + """ + Native VLAN for a trunk port. + If both `native_vlan` and `native_vlan_tag` are set, `native_vlan_tag` + takes precedence. + """ + native_vlan_tag: bool | None + """If both `native_vlan` and `native_vlan_tag` are set, `native_vlan_tag` takes precedence.""" + phone_vlan: int | None + """ + Phone VLAN for a mode `trunk phone` port. + Requires `mode: trunk phone` to be set. + """ + phone_trunk_mode: Literal["tagged", "untagged", "tagged phone", "untagged phone"] | None + """ + Specify if the phone traffic is tagged or untagged. + If both data and phone traffic are untagged, + MAC-Based VLAN Assignment (MBVA) is used, if supported by the model of switch. + """ + trunk_groups: TrunkGroups + """ + Required with `enable_trunk_groups: true`. + Trunk Groups are used for limiting VLANs on trunk ports + to VLANs with the same Trunk Group. + + + Subclass of AvdList with `str` items. + """ + vlans: str | None + """ + Interface VLANs - if not set, the EOS default is that all VLANs are allowed for trunk ports, and + VLAN 1 will be used for access ports. + """ + spanning_tree_portfast: Literal["edge", "network"] | None + spanning_tree_bpdufilter: Literal["enabled", "disabled", "True", "False", "true", "false"] | None + spanning_tree_bpduguard: Literal["enabled", "disabled", "True", "False", "true", "false"] | None + flowcontrol: Flowcontrol + """Subclass of AvdModel.""" + qos_profile: str | None + """QOS profile name.""" + ptp: Ptp + """ + The global PTP profile parameters will be applied to all connected endpoints where `ptp` is manually + enabled. + `ptp role master` is set to ensure control over the PTP topology. + + + Subclass of AvdModel. + """ + sflow: bool | None + """Configures sFlow on the interface. Overrides `fabric_sflow.endpoints` setting.""" + flow_tracking: FlowTracking + """ + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.endpoints` setting. + Subclass of AvdModel. + """ + link_tracking: LinkTracking + """ + Configure the downstream interfaces of a respective Link Tracking Group. + If `port_channel` is + defined in an adapter, then the port-channel interface is configured to be the downstream. + Else all + the ethernet interfaces will be configured as downstream -> to configure single-active EVPN + multihomed networks. + + + Subclass of AvdModel. + """ + dot1x: Dot1x + """ + 802.1x + + Subclass of AvdModel. + """ + poe: Poe + """ + Power Over Ethernet settings applied on port. Only configured if platform supports PoE. + + Subclass of + AvdModel. + """ + storm_control: StormControl + """ + Storm control settings applied on port toward the endpoint. + + Subclass of AvdModel. + """ + monitor_sessions: MonitorSessions + """ + Used to define switchports as source or destination for monitoring sessions. + + Subclass of AvdList + with `MonitorSessionsItem` items. + """ + ethernet_segment: EthernetSegment + """ + Settings for all or single-active EVPN multihoming. + + Subclass of AvdModel. + """ + port_channel: PortChannel + """ + Used for port-channel adapter. + + Subclass of AvdModel. + """ + validate_state: bool | None + """ + Set to false to disable interface state and LLDP topology validation performed by the + `eos_validate_state` role. + """ + validate_lldp: bool | None + """Set to false to disable the LLDP topology validation performed by the `eos_validate_state` role.""" + raw_eos_cli: str | None + """EOS CLI rendered directly on the ethernet interface in the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config added under ethernet_interfaces.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + switch_ports: SwitchPorts | UndefinedType = Undefined, + switches: Switches | UndefinedType = Undefined, + endpoint_ports: EndpointPorts | UndefinedType = Undefined, + descriptions: Descriptions | UndefinedType = Undefined, + speed: str | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + profile: str | None | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + mode: Literal["access", "dot1q-tunnel", "trunk", "trunk phone"] | None | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + l2_mtu: int | None | UndefinedType = Undefined, + l2_mru: int | None | UndefinedType = Undefined, + native_vlan: int | None | UndefinedType = Undefined, + native_vlan_tag: bool | None | UndefinedType = Undefined, + phone_vlan: int | None | UndefinedType = Undefined, + phone_trunk_mode: Literal["tagged", "untagged", "tagged phone", "untagged phone"] | None | UndefinedType = Undefined, + trunk_groups: TrunkGroups | UndefinedType = Undefined, + vlans: str | None | UndefinedType = Undefined, + spanning_tree_portfast: Literal["edge", "network"] | None | UndefinedType = Undefined, + spanning_tree_bpdufilter: Literal["enabled", "disabled", "True", "False", "true", "false"] | None | UndefinedType = Undefined, + spanning_tree_bpduguard: Literal["enabled", "disabled", "True", "False", "true", "false"] | None | UndefinedType = Undefined, + flowcontrol: Flowcontrol | UndefinedType = Undefined, + qos_profile: str | None | UndefinedType = Undefined, + ptp: Ptp | UndefinedType = Undefined, + sflow: bool | None | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + link_tracking: LinkTracking | UndefinedType = Undefined, + dot1x: Dot1x | UndefinedType = Undefined, + poe: Poe | UndefinedType = Undefined, + storm_control: StormControl | UndefinedType = Undefined, + monitor_sessions: MonitorSessions | UndefinedType = Undefined, + ethernet_segment: EthernetSegment | UndefinedType = Undefined, + port_channel: PortChannel | UndefinedType = Undefined, + validate_state: bool | None | UndefinedType = Undefined, + validate_lldp: bool | None | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdaptersItem. + + + Subclass of AvdModel. + + Args: + switch_ports: + List of switch interfaces. + The lists `endpoint_ports`, `switch_ports`, and `switches` must have the + same length. + + + Subclass of AvdList with `str` items. + switches: + List of switches. + The lists `endpoint_ports`, `switch_ports`, and `switches` must have the same + length. + + + Subclass of AvdList with `str` items. + endpoint_ports: + Endpoint ports is used for description, required unless `description` or `descriptions` is set. + The + lists `endpoint_ports`, `switch_ports`, `descriptions` and `switches` must have the same length. + Each list item is one switchport. + + + Subclass of AvdList with `str` items. + descriptions: + Unique description per port. When set, takes priority over description. + This can be a template using + the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom- + descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - + `endpoint_type` - the `type` from `connected_endpoints_keys` like `server`, `router` etc. + - + `endpoint` - The name of the connected endpoint + - `endpoint_port` - The value from + `endpoint_ports` for this switch port if set. + - `port_channel_id`: The port-channel number for the + switch. + + Subclass of AvdList with `Any` items. + speed: + Set adapter speed in the format `` or `forced ` or `auto + `. + If not specified speed will be auto. + description: + Description or description template to be used on all ports. + This can be a template using the AVD + string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom- + descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - + `endpoint_type` - the `type` from `connected_endpoints_keys` like `server`, `router` etc. + - + `endpoint` - The name of the connected endpoint + - `endpoint_port` - The value from + `endpoint_ports` for this switch port if set. + + The default description is set by + `default_connected_endpoints_description`. + By default the description is templated from the type, + name and port of the endpoint if set. + profile: Port-profile name to inherit configuration. + enabled: + Administrative state, setting to false will set the port to 'shutdown' in the intended + configuration. + mode: Interface mode. + mtu: mtu + l2_mtu: "l2_mtu" should only be defined for platforms supporting the "l2 mtu" CLI. + l2_mru: "l2_mru" should only be defined for platforms supporting the "l2 mru" CLI. + native_vlan: + Native VLAN for a trunk port. + If both `native_vlan` and `native_vlan_tag` are set, `native_vlan_tag` + takes precedence. + native_vlan_tag: If both `native_vlan` and `native_vlan_tag` are set, `native_vlan_tag` takes precedence. + phone_vlan: + Phone VLAN for a mode `trunk phone` port. + Requires `mode: trunk phone` to be set. + phone_trunk_mode: + Specify if the phone traffic is tagged or untagged. + If both data and phone traffic are untagged, + MAC-Based VLAN Assignment (MBVA) is used, if supported by the model of switch. + trunk_groups: + Required with `enable_trunk_groups: true`. + Trunk Groups are used for limiting VLANs on trunk ports + to VLANs with the same Trunk Group. + + + Subclass of AvdList with `str` items. + vlans: + Interface VLANs - if not set, the EOS default is that all VLANs are allowed for trunk ports, and + VLAN 1 will be used for access ports. + spanning_tree_portfast: spanning_tree_portfast + spanning_tree_bpdufilter: spanning_tree_bpdufilter + spanning_tree_bpduguard: spanning_tree_bpduguard + flowcontrol: Subclass of AvdModel. + qos_profile: QOS profile name. + ptp: + The global PTP profile parameters will be applied to all connected endpoints where `ptp` is manually + enabled. + `ptp role master` is set to ensure control over the PTP topology. + + + Subclass of AvdModel. + sflow: Configures sFlow on the interface. Overrides `fabric_sflow.endpoints` setting. + flow_tracking: + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.endpoints` setting. + Subclass of AvdModel. + link_tracking: + Configure the downstream interfaces of a respective Link Tracking Group. + If `port_channel` is + defined in an adapter, then the port-channel interface is configured to be the downstream. + Else all + the ethernet interfaces will be configured as downstream -> to configure single-active EVPN + multihomed networks. + + + Subclass of AvdModel. + dot1x: + 802.1x + + Subclass of AvdModel. + poe: + Power Over Ethernet settings applied on port. Only configured if platform supports PoE. + + Subclass of + AvdModel. + storm_control: + Storm control settings applied on port toward the endpoint. + + Subclass of AvdModel. + monitor_sessions: + Used to define switchports as source or destination for monitoring sessions. + + Subclass of AvdList + with `MonitorSessionsItem` items. + ethernet_segment: + Settings for all or single-active EVPN multihoming. + + Subclass of AvdModel. + port_channel: + Used for port-channel adapter. + + Subclass of AvdModel. + validate_state: + Set to false to disable interface state and LLDP topology validation performed by the + `eos_validate_state` role. + validate_lldp: Set to false to disable the LLDP topology validation performed by the `eos_validate_state` role. + raw_eos_cli: EOS CLI rendered directly on the ethernet interface in the final EOS configuration. + structured_config: + Custom structured config added under ethernet_interfaces.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Adapters(AvdList[AdaptersItem]): + """Subclass of AvdList with `AdaptersItem` items.""" + + Adapters._item_type = AdaptersItem + + _fields: ClassVar[dict] = {"name": {"type": str}, "rack": {"type": str}, "adapters": {"type": Adapters}, "_custom_data": {"type": dict}} + name: str + """Endpoint name will be used in the switchport description.""" + rack: str | None + """Rack is used for documentation purposes only.""" + adapters: Adapters + """ + A list of adapters, group by adapters leveraging the same port-profile. + + Subclass of AvdList with + `AdaptersItem` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + rack: str | None | UndefinedType = Undefined, + adapters: Adapters | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + ConnectedEndpointsItem. + + + Subclass of AvdModel. + + Args: + name: Endpoint name will be used in the switchport description. + rack: Rack is used for documentation purposes only. + adapters: + A list of adapters, group by adapters leveraging the same port-profile. + + Subclass of AvdList with + `AdaptersItem` items. + _custom_data: _custom_data + + """ + + class ConnectedEndpoints(AvdIndexedList[str, ConnectedEndpointsItem]): + """Subclass of AvdIndexedList with `ConnectedEndpointsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + ConnectedEndpoints._item_type = ConnectedEndpointsItem + + _fields: ClassVar[dict] = {"key": {"type": str}, "value": {"type": ConnectedEndpoints}} + _field_to_key_map: ClassVar[dict] = {"value": "connected_endpoints_keys_key"} + _key_to_field_map: ClassVar[dict] = {"connected_endpoints_keys_key": "value"} + key: str + """Key used as dynamic key""" + value: ConnectedEndpoints + """Value of dynamic key""" + + if TYPE_CHECKING: + + def __init__(self, *, key: str | UndefinedType = Undefined, value: ConnectedEndpoints | UndefinedType = Undefined) -> None: + """ + DynamicConnectedEndpointsItem. + + + Args: + key: Key used as dynamic key + value: Value of dynamic key + + """ + + class DynamicConnectedEndpoints(AvdIndexedList[str, DynamicConnectedEndpointsItem]): + _primary_key: ClassVar[str] = "key" + + DynamicConnectedEndpoints._item_type = DynamicConnectedEndpointsItem + + class DynamicCustomNodeTypesItem(AvdModel): + class CustomNodeTypes(AvdModel): + """Subclass of AvdModel.""" + + class Defaults(AvdModel): + """Subclass of AvdModel.""" + + class LinkTracking(AvdModel): + """Subclass of AvdModel.""" + + class GroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "recovery_delay": {"type": int}, + "links_minimum": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str | None + """Tracking group name.""" + recovery_delay: int | None + """default -> platform_settings_mlag_reload_delay -> 300.""" + links_minimum: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + recovery_delay: int | None | UndefinedType = Undefined, + links_minimum: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GroupsItem. + + + Subclass of AvdModel. + + Args: + name: Tracking group name. + recovery_delay: default -> platform_settings_mlag_reload_delay -> 300. + links_minimum: links_minimum + _custom_data: _custom_data + + """ + + class Groups(AvdList[GroupsItem]): + """Subclass of AvdList with `GroupsItem` items.""" + + Groups._item_type = GroupsItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "groups": {"type": Groups, "default": lambda cls: coerce_type([{"name": "LT_GROUP1"}], target_type=cls)}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + groups: Groups + """ + Link Tracking Groups. + By default a single group named "LT_GROUP1" is defined with default values. + Any groups defined under "groups" will replace the default. + + + Subclass of AvdList with `GroupsItem` + items. + + Default value: `lambda cls: coerce_type([{"name": "LT_GROUP1"}], target_type=cls)` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + groups: + Link Tracking Groups. + By default a single group named "LT_GROUP1" is defined with default values. + Any groups defined under "groups" will replace the default. + + + Subclass of AvdList with `GroupsItem` + items. + _custom_data: _custom_data + + """ + + class LacpPortIdRange(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "size": {"type": int, "default": 128}, + "offset": {"type": int, "default": 0}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + size: int + """ + Recommended size > = number of ports in the switch. + + Default value: `128` + """ + offset: int + """ + Offset is used to avoid overlapping port-id ranges of different switches. + Useful when a "connected- + endpoint" is connected to switches in different "node_groups". + + Default value: `0` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + size: int | UndefinedType = Undefined, + offset: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LacpPortIdRange. + + + Subclass of AvdModel. + + Args: + enabled: enabled + size: Recommended size > = number of ports in the switch. + offset: + Offset is used to avoid overlapping port-id ranges of different switches. + Useful when a "connected- + endpoint" is connected to switches in different "node_groups". + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen): + """Subclass of AvdModel.""" + + class UplinkInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkInterfaces._item_type = str + + class UplinkSwitchInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkSwitchInterfaces._item_type = str + + class UplinkSwitches(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkSwitches._item_type = str + + class UplinkPtp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enable": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enable: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, enable: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + UplinkPtp. + + + Subclass of AvdModel. + + Args: + enable: enable + _custom_data: _custom_data + + """ + + class UplinkMacsec(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "_custom_data": {"type": dict}} + profile: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, profile: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + UplinkMacsec. + + + Subclass of AvdModel. + + Args: + profile: profile + _custom_data: _custom_data + + """ + + class MlagPortChannelStructuredConfig(EosCliConfigGen.PortChannelInterfacesItem): + """Subclass of AvdModel.""" + + class MlagPeerVlanStructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + class MlagPeerL3VlanStructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + class BgpDefaults(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + BgpDefaults._item_type = str + + class EvpnRouteServers(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + EvpnRouteServers._item_type = str + + class Filter(AvdModel): + """Subclass of AvdModel.""" + + class Tenants(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tenants._item_type = str + + class Tags(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tags._item_type = str + + class AllowVrfs(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AllowVrfs._item_type = str + + class DenyVrfs(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DenyVrfs._item_type = str + + class AlwaysIncludeVrfsInTenants(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AlwaysIncludeVrfsInTenants._item_type = str + + _fields: ClassVar[dict] = { + "tenants": {"type": Tenants, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "tags": {"type": Tags, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "allow_vrfs": {"type": AllowVrfs, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "deny_vrfs": {"type": DenyVrfs, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "always_include_vrfs_in_tenants": {"type": AlwaysIncludeVrfsInTenants}, + "only_vlans_in_use": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + tenants: Tenants + """ + Limit configured Network Services to those defined under these Tenants. Set to ['all'] for all + Tenants (default). + This list also limits Tenants included by `always_include_vrfs_in_tenants`. + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + tags: Tags + """ + Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default). + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + allow_vrfs: AllowVrfs + """ + Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs + (default). + This list also limits VRFs included by `always_include_vrfs_in_tenants`. + + Subclass of + AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + deny_vrfs: DenyVrfs + """ + Prevent configuration of Network Services defined under these VRFs. + This list prevents the given + VRFs to be included by any other filtering mechanism. + + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + always_include_vrfs_in_tenants: AlwaysIncludeVrfsInTenants + """ + List of tenants where VRFs will be configured even if VLANs are not included in tags. + Useful for L3 + "border" leaf. + + + Subclass of AvdList with `str` items. + """ + only_vlans_in_use: bool + """ + Only configure VLANs, SVIs, VRFs in use by connected endpoints or downstream L2 switches. + Note! This + feature only considers configuration managed by eos_designs. + This excludes structured_config, + custom_structured_configuration_, raw_eos_cli, eos_cli, custom templates, configlets etc. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + tenants: Tenants | UndefinedType = Undefined, + tags: Tags | UndefinedType = Undefined, + allow_vrfs: AllowVrfs | UndefinedType = Undefined, + deny_vrfs: DenyVrfs | UndefinedType = Undefined, + always_include_vrfs_in_tenants: AlwaysIncludeVrfsInTenants | UndefinedType = Undefined, + only_vlans_in_use: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Filter. + + + Subclass of AvdModel. + + Args: + tenants: + Limit configured Network Services to those defined under these Tenants. Set to ['all'] for all + Tenants (default). + This list also limits Tenants included by `always_include_vrfs_in_tenants`. + Subclass of AvdList with `str` items. + tags: + Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default). + Subclass of AvdList with `str` items. + allow_vrfs: + Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs + (default). + This list also limits VRFs included by `always_include_vrfs_in_tenants`. + + Subclass of + AvdList with `str` items. + deny_vrfs: + Prevent configuration of Network Services defined under these VRFs. + This list prevents the given + VRFs to be included by any other filtering mechanism. + + Subclass of AvdList with `str` items. + always_include_vrfs_in_tenants: + List of tenants where VRFs will be configured even if VLANs are not included in tags. + Useful for L3 + "border" leaf. + + + Subclass of AvdList with `str` items. + only_vlans_in_use: + Only configure VLANs, SVIs, VRFs in use by connected endpoints or downstream L2 switches. + Note! This + feature only considers configuration managed by eos_designs. + This excludes structured_config, + custom_structured_configuration_, raw_eos_cli, eos_cli, custom templates, configlets etc. + _custom_data: _custom_data + + """ + + class EvpnGateway(AvdModel): + """Subclass of AvdModel.""" + + class RemotePeersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hostname": {"type": str}, + "ip_address": {"type": str}, + "bgp_as": {"type": str}, + "_custom_data": {"type": dict}, + } + hostname: str + """Hostname of remote EVPN GW server.""" + ip_address: str | None + """Peering IP of remote Route Server.""" + bgp_as: str | None + """ + Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being + interpreted as a float number. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: str | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + bgp_as: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemotePeersItem. + + + Subclass of AvdModel. + + Args: + hostname: Hostname of remote EVPN GW server. + ip_address: Peering IP of remote Route Server. + bgp_as: + Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being + interpreted as a float number. + _custom_data: _custom_data + + """ + + class RemotePeers(AvdIndexedList[str, RemotePeersItem]): + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + + _primary_key: ClassVar[str] = "hostname" + + RemotePeers._item_type = RemotePeersItem + + class EvpnL2(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enabled: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, enabled: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + EvpnL2. + + + Subclass of AvdModel. + + Args: + enabled: enabled + _custom_data: _custom_data + + """ + + class EvpnL3(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "inter_domain": {"type": bool, "default": True}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + inter_domain: bool + """Default value: `True`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + inter_domain: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnL3. + + + Subclass of AvdModel. + + Args: + enabled: enabled + inter_domain: inter_domain + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "remote_peers": {"type": RemotePeers}, + "evpn_l2": {"type": EvpnL2}, + "evpn_l3": {"type": EvpnL3}, + "_custom_data": {"type": dict}, + } + remote_peers: RemotePeers + """ + Define remote peers of the EVPN VXLAN Gateway. + If the hostname can be found in the inventory, + ip_address and BGP ASN will be automatically populated. Manual override takes precedence. + If the + peer's hostname can not be found in the inventory, ip_address and bgp_as must be defined. + + + Subclass + of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + """ + evpn_l2: EvpnL2 + """ + Enable EVPN Gateway functionality for route-types 2 (MAC-IP) and 3 (IMET). + + Subclass of AvdModel. + """ + evpn_l3: EvpnL3 + """ + Enable EVPN Gateway functionality for route-type 5 (IP-PREFIX). + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + remote_peers: RemotePeers | UndefinedType = Undefined, + evpn_l2: EvpnL2 | UndefinedType = Undefined, + evpn_l3: EvpnL3 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnGateway. + + + Subclass of AvdModel. + + Args: + remote_peers: + Define remote peers of the EVPN VXLAN Gateway. + If the hostname can be found in the inventory, + ip_address and BGP ASN will be automatically populated. Manual override takes precedence. + If the + peer's hostname can not be found in the inventory, ip_address and bgp_as must be defined. + + + Subclass + of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + evpn_l2: + Enable EVPN Gateway functionality for route-types 2 (MAC-IP) and 3 (IMET). + + Subclass of AvdModel. + evpn_l3: + Enable EVPN Gateway functionality for route-type 5 (IP-PREFIX). + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class IpvpnGateway(AvdModel): + """Subclass of AvdModel.""" + + class AddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AddressFamilies._item_type = str + + class RemotePeersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hostname": {"type": str}, + "ip_address": {"type": str}, + "bgp_as": {"type": str}, + "_custom_data": {"type": dict}, + } + hostname: str + """Hostname of remote IPVPN Peer.""" + ip_address: str + """Peering IP of remote IPVPN Peer.""" + bgp_as: str + """ + Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For + asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted + as a float number. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: str | UndefinedType = Undefined, + ip_address: str | UndefinedType = Undefined, + bgp_as: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemotePeersItem. + + + Subclass of AvdModel. + + Args: + hostname: Hostname of remote IPVPN Peer. + ip_address: Peering IP of remote IPVPN Peer. + bgp_as: + Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For + asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted + as a float number. + _custom_data: _custom_data + + """ + + class RemotePeers(AvdIndexedList[str, RemotePeersItem]): + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + + _primary_key: ClassVar[str] = "hostname" + + RemotePeers._item_type = RemotePeersItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "evpn_domain_id": {"type": str, "default": "65535:1"}, + "ipvpn_domain_id": {"type": str, "default": "65535:2"}, + "enable_d_path": {"type": bool, "default": True}, + "maximum_routes": {"type": int, "default": 0}, + "local_as": {"type": str}, + "address_families": {"type": AddressFamilies, "default": lambda cls: coerce_type(["vpn-ipv4"], target_type=cls)}, + "remote_peers": {"type": RemotePeers}, + "_custom_data": {"type": dict}, + } + enabled: bool + evpn_domain_id: str + """ + Domain ID to assign to EVPN address family for use with D-path. Format :. + + Default value: `"65535:1"` + """ + ipvpn_domain_id: str + """ + Domain ID to assign to IPVPN address families for use with D-path. Format :. + + Default value: `"65535:2"` + """ + enable_d_path: bool + """ + Enable D-path for use with BGP bestpath selection algorithm. + + Default value: `True` + """ + maximum_routes: int + """ + Maximum routes to accept from IPVPN remote peers. + + Default value: `0` + """ + local_as: str | None + """ + Local BGP AS applied to peering with IPVPN remote peers. + BGP AS <1-4294967295> or AS number in asdot + notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number. + """ + address_families: AddressFamilies + """ + IPVPN address families to enable for remote peers. + + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["vpn-ipv4"], target_type=cls)` + """ + remote_peers: RemotePeers + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + evpn_domain_id: str | UndefinedType = Undefined, + ipvpn_domain_id: str | UndefinedType = Undefined, + enable_d_path: bool | UndefinedType = Undefined, + maximum_routes: int | UndefinedType = Undefined, + local_as: str | None | UndefinedType = Undefined, + address_families: AddressFamilies | UndefinedType = Undefined, + remote_peers: RemotePeers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpvpnGateway. + + + Subclass of AvdModel. + + Args: + enabled: enabled + evpn_domain_id: Domain ID to assign to EVPN address family for use with D-path. Format :. + ipvpn_domain_id: Domain ID to assign to IPVPN address families for use with D-path. Format :. + enable_d_path: Enable D-path for use with BGP bestpath selection algorithm. + maximum_routes: Maximum routes to accept from IPVPN remote peers. + local_as: + Local BGP AS applied to peering with IPVPN remote peers. + BGP AS <1-4294967295> or AS number in asdot + notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number. + address_families: + IPVPN address families to enable for remote peers. + + Subclass of AvdList with `str` items. + remote_peers: Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + _custom_data: _custom_data + + """ + + class MlagInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MlagInterfaces._item_type = str + + class OverlayAddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + OverlayAddressFamilies._item_type = str + + class MplsRouteReflectors(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MplsRouteReflectors._item_type = str + + class Ptp(AvdModel): + """Subclass of AvdModel.""" + + class Dscp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"general_messages": {"type": int}, "event_messages": {"type": int}, "_custom_data": {"type": dict}} + general_messages: int | None + event_messages: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + general_messages: int | None | UndefinedType = Undefined, + event_messages: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dscp. + + + Subclass of AvdModel. + + Args: + general_messages: general_messages + event_messages: event_messages + _custom_data: _custom_data + + """ + + class Monitor(AvdModel): + """Subclass of AvdModel.""" + + class Threshold(AvdModel): + """Subclass of AvdModel.""" + + class Drop(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "offset_from_master": {"type": int}, + "mean_path_delay": {"type": int}, + "_custom_data": {"type": dict}, + } + offset_from_master: int | None + mean_path_delay: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + offset_from_master: int | None | UndefinedType = Undefined, + mean_path_delay: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Drop. + + + Subclass of AvdModel. + + Args: + offset_from_master: offset_from_master + mean_path_delay: mean_path_delay + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "offset_from_master": {"type": int, "default": 250}, + "mean_path_delay": {"type": int, "default": 1500}, + "drop": {"type": Drop}, + "_custom_data": {"type": dict}, + } + offset_from_master: int + """Default value: `250`""" + mean_path_delay: int + """Default value: `1500`""" + drop: Drop + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + offset_from_master: int | UndefinedType = Undefined, + mean_path_delay: int | UndefinedType = Undefined, + drop: Drop | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Threshold. + + + Subclass of AvdModel. + + Args: + offset_from_master: offset_from_master + mean_path_delay: mean_path_delay + drop: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MissingMessage(AvdModel): + """Subclass of AvdModel.""" + + class Intervals(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "announce": {"type": int}, + "follow_up": {"type": int}, + "sync": {"type": int}, + "_custom_data": {"type": dict}, + } + announce: int | None + follow_up: int | None + sync: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + announce: int | None | UndefinedType = Undefined, + follow_up: int | None | UndefinedType = Undefined, + sync: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Intervals. + + + Subclass of AvdModel. + + Args: + announce: announce + follow_up: follow_up + sync: sync + _custom_data: _custom_data + + """ + + class SequenceIds(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "announce": {"type": int, "default": 3}, + "delay_resp": {"type": int, "default": 3}, + "follow_up": {"type": int, "default": 3}, + "sync": {"type": int, "default": 3}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + announce: int + """Default value: `3`""" + delay_resp: int + """Default value: `3`""" + follow_up: int + """Default value: `3`""" + sync: int + """Default value: `3`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + announce: int | UndefinedType = Undefined, + delay_resp: int | UndefinedType = Undefined, + follow_up: int | UndefinedType = Undefined, + sync: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceIds. + + + Subclass of AvdModel. + + Args: + enabled: enabled + announce: announce + delay_resp: delay_resp + follow_up: follow_up + sync: sync + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "intervals": {"type": Intervals}, + "sequence_ids": {"type": SequenceIds}, + "_custom_data": {"type": dict}, + } + intervals: Intervals + """Subclass of AvdModel.""" + sequence_ids: SequenceIds + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + intervals: Intervals | UndefinedType = Undefined, + sequence_ids: SequenceIds | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingMessage. + + + Subclass of AvdModel. + + Args: + intervals: Subclass of AvdModel. + sequence_ids: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "threshold": {"type": Threshold}, + "missing_message": {"type": MissingMessage}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + threshold: Threshold + """Subclass of AvdModel.""" + missing_message: MissingMessage + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + threshold: Threshold | UndefinedType = Undefined, + missing_message: MissingMessage | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Monitor. + + + Subclass of AvdModel. + + Args: + enabled: enabled + threshold: Subclass of AvdModel. + missing_message: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "profile": {"type": str}, + "mlag": {"type": bool, "default": False}, + "domain": {"type": int, "default": 127}, + "priority1": {"type": int}, + "priority2": {"type": int}, + "auto_clock_identity": {"type": bool}, + "clock_identity_prefix": {"type": str, "default": "00:1C:73"}, + "clock_identity": {"type": str}, + "source_ip": {"type": str}, + "mode": {"type": str, "default": "boundary"}, + "mode_one_step": {"type": bool, "default": False}, + "ttl": {"type": int}, + "forward_unicast": {"type": bool, "default": False}, + "dscp": {"type": Dscp}, + "monitor": {"type": Monitor}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + profile: str | None + """ + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + """ + mlag: bool + """ + Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be + configured on the MLAG peer-link port-channel. + + Default value: `False` + """ + domain: int + """Default value: `127`""" + priority1: int | None + """default -> automatically set based on node_type.""" + priority2: int | None + """default -> (node_id modulus 256).""" + auto_clock_identity: bool | None + """ + If you prefer to have PTP clock identity be the system MAC-address of the switch, which is the + default EOS behaviour, simply disable the automatic PTP clock identity. + default -> + (clock_identity_prefix = 00:1C:73 (default)) + (PTP priority 1 as HEX) + ":00:" + (PTP priority 2 as + HEX). + """ + clock_identity_prefix: str + """ + PTP clock idetentiy 3-byte prefix. i.e. "01:02:03". + By default the 3-byte prefix is "00:1C:73". + This + can be overridden if auto_clock_identity is set to true (which is the default). + + Default value: `"00:1C:73"` + """ + clock_identity: str | None + """Set PTP clock identity manually. 6-byte value i.e. "01:02:03:04:05:06".""" + source_ip: str | None + """ + By default in EOS, PTP packets are sourced with an IP address from the routed port or from the + relevant SVI, which is the recommended behaviour. + This can be set manually if required, for example, + to a value of "10.1.2.3". + """ + mode: Literal["boundary"] + """Default value: `"boundary"`""" + mode_one_step: bool + """Default value: `False`""" + ttl: int | None + forward_unicast: bool + """ + Enable PTP unicast forwarding. + + Default value: `False` + """ + dscp: Dscp + """Subclass of AvdModel.""" + monitor: Monitor + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + profile: str | None | UndefinedType = Undefined, + mlag: bool | UndefinedType = Undefined, + domain: int | UndefinedType = Undefined, + priority1: int | None | UndefinedType = Undefined, + priority2: int | None | UndefinedType = Undefined, + auto_clock_identity: bool | None | UndefinedType = Undefined, + clock_identity_prefix: str | UndefinedType = Undefined, + clock_identity: str | None | UndefinedType = Undefined, + source_ip: str | None | UndefinedType = Undefined, + mode: Literal["boundary"] | UndefinedType = Undefined, + mode_one_step: bool | UndefinedType = Undefined, + ttl: int | None | UndefinedType = Undefined, + forward_unicast: bool | UndefinedType = Undefined, + dscp: Dscp | UndefinedType = Undefined, + monitor: Monitor | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ptp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + profile: + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + mlag: + Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be + configured on the MLAG peer-link port-channel. + domain: domain + priority1: default -> automatically set based on node_type. + priority2: default -> (node_id modulus 256). + auto_clock_identity: + If you prefer to have PTP clock identity be the system MAC-address of the switch, which is the + default EOS behaviour, simply disable the automatic PTP clock identity. + default -> + (clock_identity_prefix = 00:1C:73 (default)) + (PTP priority 1 as HEX) + ":00:" + (PTP priority 2 as + HEX). + clock_identity_prefix: + PTP clock idetentiy 3-byte prefix. i.e. "01:02:03". + By default the 3-byte prefix is "00:1C:73". + This + can be overridden if auto_clock_identity is set to true (which is the default). + clock_identity: Set PTP clock identity manually. 6-byte value i.e. "01:02:03:04:05:06". + source_ip: + By default in EOS, PTP packets are sourced with an IP address from the routed port or from the + relevant SVI, which is the recommended behaviour. + This can be set manually if required, for example, + to a value of "10.1.2.3". + mode: mode + mode_one_step: mode_one_step + ttl: ttl + forward_unicast: Enable PTP unicast forwarding. + dscp: Subclass of AvdModel. + monitor: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class WanHa(AvdModel): + """Subclass of AvdModel.""" + + class HaInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + HaInterfaces._item_type = str + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "ipsec": {"type": bool, "default": True}, + "mtu": {"type": int, "default": 9194}, + "ha_interfaces": {"type": HaInterfaces}, + "ha_ipv4_pool": {"type": str}, + "max_ha_interfaces": {"type": int}, + "port_channel_id": {"type": int}, + "use_port_channel_for_direct_ha": {"type": bool, "default": True}, + "flow_tracking": {"type": FlowTracking}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group.""" + ipsec: bool + """ + Enable / Disable IPsec over HA path-group when HA is enabled. + + Default value: `True` + """ + mtu: int + """ + Set MTU on WAN HA interfaces. + + Default value: `9194` + """ + ha_interfaces: HaInterfaces + """ + Local WAN HA interfaces + Overwrite the default behavior which is to pick all the `uplink_interfaces`. + Can be used to filter uplink interfaces when there are multiple uplinks. + Limitations: + Either all + interfaces must be uplinks or all interfaces must not be uplinks. + Only one interface is supported + for non uplinks. + + Subclass of AvdList with `str` items. + """ + ha_ipv4_pool: str | None + """ + IP address pool used for WAN HA connectivity. + IP is derived from the node ID. + Not used for uplink + interfaces. + """ + max_ha_interfaces: int | None + """ + Number of parallel links towards HA switches. + Can be used to reserve IP addresses for future + parallel HA links. + """ + port_channel_id: int | None + """Port-channel ID to use for direct HA.""" + use_port_channel_for_direct_ha: bool + """ + Enable or disable using a port-channel interface for direct HA when there is only one interface. + This feature was introduced in EOS 4.33.0F. + + Default value: `True` + """ + flow_tracking: FlowTracking + """ + Configures flow-tracking on the HA interfaces. Overrides `fabric_flow_tracking.wan_ha_links` + setting. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + ipsec: bool | UndefinedType = Undefined, + mtu: int | UndefinedType = Undefined, + ha_interfaces: HaInterfaces | UndefinedType = Undefined, + ha_ipv4_pool: str | None | UndefinedType = Undefined, + max_ha_interfaces: int | None | UndefinedType = Undefined, + port_channel_id: int | None | UndefinedType = Undefined, + use_port_channel_for_direct_ha: bool | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + WanHa. + + + Subclass of AvdModel. + + Args: + enabled: Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group. + ipsec: Enable / Disable IPsec over HA path-group when HA is enabled. + mtu: Set MTU on WAN HA interfaces. + ha_interfaces: + Local WAN HA interfaces + Overwrite the default behavior which is to pick all the `uplink_interfaces`. + Can be used to filter uplink interfaces when there are multiple uplinks. + Limitations: + Either all + interfaces must be uplinks or all interfaces must not be uplinks. + Only one interface is supported + for non uplinks. + + Subclass of AvdList with `str` items. + ha_ipv4_pool: + IP address pool used for WAN HA connectivity. + IP is derived from the node ID. + Not used for uplink + interfaces. + max_ha_interfaces: + Number of parallel links towards HA switches. + Can be used to reserve IP addresses for future + parallel HA links. + port_channel_id: Port-channel ID to use for direct HA. + use_port_channel_for_direct_ha: + Enable or disable using a port-channel interface for direct HA when there is only one interface. + This feature was introduced in EOS 4.33.0F. + flow_tracking: + Configures flow-tracking on the HA interfaces. Overrides `fabric_flow_tracking.wan_ha_links` + setting. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L3InterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "peer_as": {"type": str}, + "ipv4_prefix_list_in": {"type": str}, + "ipv4_prefix_list_out": {"type": str}, + "_custom_data": {"type": dict}, + } + peer_as: str + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + ipv4_prefix_list_in: str | None + """ + Prefix List Name. Accept routes for only these prefixes from the peer. + Required for wan interfaces. + """ + ipv4_prefix_list_out: str | None + """ + Prefix List Name. Advertise routes for only these prefixes. + If not specified, nothing would be + advertised. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + peer_as: str | UndefinedType = Undefined, + ipv4_prefix_list_in: str | None | UndefinedType = Undefined, + ipv4_prefix_list_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + peer_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + ipv4_prefix_list_in: + Prefix List Name. Accept routes for only these prefixes from the peer. + Required for wan interfaces. + ipv4_prefix_list_out: + Prefix List Name. Advertise routes for only these prefixes. + If not specified, nothing would be + advertised. + _custom_data: _custom_data + + """ + + class StaticRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "_custom_data": {"type": dict}} + prefix: str + """IPv4_network/Mask.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, prefix: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + StaticRoutesItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv4_network/Mask. + _custom_data: _custom_data + + """ + + class StaticRoutes(AvdList[StaticRoutesItem]): + """Subclass of AvdList with `StaticRoutesItem` items.""" + + StaticRoutes._item_type = StaticRoutesItem + + class CvPathfinderInternetExit(AvdModel): + """Subclass of AvdModel.""" + + class PoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "tunnel_interface_numbers": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Internet-exit policy name.""" + tunnel_interface_numbers: str | None + """ + Number range to use for Tunnel interfaces to an internet-exit service provider using this local + interface. + Examples: '1-3' or '100,200,300' + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + tunnel_interface_numbers: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PoliciesItem. + + + Subclass of AvdModel. + + Args: + name: Internet-exit policy name. + tunnel_interface_numbers: + Number range to use for Tunnel interfaces to an internet-exit service provider using this local + interface. + Examples: '1-3' or '100,200,300' + _custom_data: _custom_data + + """ + + class Policies(AvdIndexedList[str, PoliciesItem]): + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Policies._item_type = PoliciesItem + + _fields: ClassVar[dict] = {"policies": {"type": Policies}, "_custom_data": {"type": dict}} + policies: Policies + """ + List of Internet-exit policies using this interface as exit. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, policies: Policies | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + CvPathfinderInternetExit. + + + Subclass of AvdModel. + + Args: + policies: + List of Internet-exit policies using this interface as exit. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "profile": {"type": str}, + "name": {"type": str}, + "description": {"type": str}, + "ip_address": {"type": str}, + "dhcp_ip": {"type": str}, + "public_ip": {"type": str}, + "encapsulation_dot1q_vlan": {"type": int}, + "dhcp_accept_default_route": {"type": bool, "default": True}, + "enabled": {"type": bool, "default": True}, + "speed": {"type": str}, + "peer": {"type": str}, + "peer_interface": {"type": str}, + "peer_ip": {"type": str}, + "bgp": {"type": Bgp}, + "ipv4_acl_in": {"type": str}, + "ipv4_acl_out": {"type": str}, + "static_routes": {"type": StaticRoutes}, + "qos_profile": {"type": str}, + "wan_carrier": {"type": str}, + "wan_circuit_id": {"type": str}, + "connected_to_pathfinder": {"type": bool, "default": True}, + "cv_pathfinder_internet_exit": {"type": CvPathfinderInternetExit}, + "raw_eos_cli": {"type": str}, + "flow_tracking": {"type": FlowTracking}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + profile: str | None + """L3 interface profile name. Profile defined under `l3_interface_profiles`.""" + name: str + """ + Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. + For a + subinterface, the parent physical interface is automatically created. + """ + description: str | None + """ + Interface description. + If not set a default description will be configured with '[[ + ]]'. + """ + ip_address: str | None + """Node IPv4 address/Mask or 'dhcp'.""" + dhcp_ip: str | None + """ + When the `ip_address` is `dhcp`, this optional field allows to indicate the expected + IPv4 address + (without mask) to be allocated on the interface if known. + This is not rendered in the configuration + but can be used for substitution of 'interface_ip' in the Access-list + set under `ipv4_acl_in` and + `ipv4_acl_out`. + """ + public_ip: str | None + """ + Node IPv4 address (no mask). + + This is used to get the public IP (if known) when the device is behind + NAT. + This is only used for `wan_rr` routers (AutoVPN RRs and Pathfinders) to determine the Public IP + with the following preference: + `wan_route_servers.path_groups.interfaces.ip_address` + -> + `l3_interfaces.public_ip` + -> `l3_interfaces.ip_address` + + The determined Public IP is used + by WAN routers when peering with this interface. + """ + encapsulation_dot1q_vlan: int | None + """ + For subinterfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + """ + dhcp_accept_default_route: bool + """ + Accept a default route from DHCP if `ip_address` is set to `dhcp`. + + Default value: `True` + """ + enabled: bool + """ + Enable or Shutdown the interface. + + Default value: `True` + """ + speed: str | None + """ + Speed should be set in the format `` or `forced ` or `auto + `. + """ + peer: str | None + """The peer device name. Used for description and documentation.""" + peer_interface: str | None + """The peer device interface. Used for description and documentation.""" + peer_ip: str | None + """ + The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true + and `ip` is an IP address. + """ + bgp: Bgp + """ + Enforce IPv4 BGP peering for the peer + + Subclass of AvdModel. + """ + ipv4_acl_in: str | None + """ + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + Required + for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under + `wan_carriers`. + """ + ipv4_acl_out: str | None + """ + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + """ + static_routes: StaticRoutes + """ + Configure IPv4 static routes pointing to `peer_ip`. + + Subclass of AvdList with `StaticRoutesItem` + items. + """ + qos_profile: str | None + """QOS service profile.""" + wan_carrier: str | None + """ + The WAN carrier this interface is connected to. + This is used to infer the path-groups in which this + interface should be configured. + Unless the carrier is marked as 'trusted' under `wan_carriers`, + `ipv4_acl_in` is also required on all WAN interfaces. + """ + wan_circuit_id: str | None + """ + The WAN circuit ID for this interface. + This is not rendered in the configuration but used for WAN + designs. + """ + connected_to_pathfinder: bool + """ + For a WAN interface (`wan_carrier` is set), allow to disable the static tunnel towards Pathfinders. + + Default value: `True` + """ + cv_pathfinder_internet_exit: CvPathfinderInternetExit + """ + PREVIEW: This key is in preview mode + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the interface in the final EOS configuration.""" + flow_tracking: FlowTracking + """ + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + """ + structured_config: StructuredConfig + """ + Custom structured config for the Ethernet interface. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | None | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + dhcp_ip: str | None | UndefinedType = Undefined, + public_ip: str | None | UndefinedType = Undefined, + encapsulation_dot1q_vlan: int | None | UndefinedType = Undefined, + dhcp_accept_default_route: bool | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + speed: str | None | UndefinedType = Undefined, + peer: str | None | UndefinedType = Undefined, + peer_interface: str | None | UndefinedType = Undefined, + peer_ip: str | None | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + ipv4_acl_in: str | None | UndefinedType = Undefined, + ipv4_acl_out: str | None | UndefinedType = Undefined, + static_routes: StaticRoutes | UndefinedType = Undefined, + qos_profile: str | None | UndefinedType = Undefined, + wan_carrier: str | None | UndefinedType = Undefined, + wan_circuit_id: str | None | UndefinedType = Undefined, + connected_to_pathfinder: bool | UndefinedType = Undefined, + cv_pathfinder_internet_exit: CvPathfinderInternetExit | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L3InterfacesItem. + + + Subclass of AvdModel. + + Args: + profile: L3 interface profile name. Profile defined under `l3_interface_profiles`. + name: + Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. + For a + subinterface, the parent physical interface is automatically created. + description: + Interface description. + If not set a default description will be configured with '[[ + ]]'. + ip_address: Node IPv4 address/Mask or 'dhcp'. + dhcp_ip: + When the `ip_address` is `dhcp`, this optional field allows to indicate the expected + IPv4 address + (without mask) to be allocated on the interface if known. + This is not rendered in the configuration + but can be used for substitution of 'interface_ip' in the Access-list + set under `ipv4_acl_in` and + `ipv4_acl_out`. + public_ip: + Node IPv4 address (no mask). + + This is used to get the public IP (if known) when the device is behind + NAT. + This is only used for `wan_rr` routers (AutoVPN RRs and Pathfinders) to determine the Public IP + with the following preference: + `wan_route_servers.path_groups.interfaces.ip_address` + -> + `l3_interfaces.public_ip` + -> `l3_interfaces.ip_address` + + The determined Public IP is used + by WAN routers when peering with this interface. + encapsulation_dot1q_vlan: + For subinterfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + dhcp_accept_default_route: Accept a default route from DHCP if `ip_address` is set to `dhcp`. + enabled: Enable or Shutdown the interface. + speed: + Speed should be set in the format `` or `forced ` or `auto + `. + peer: The peer device name. Used for description and documentation. + peer_interface: The peer device interface. Used for description and documentation. + peer_ip: + The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true + and `ip` is an IP address. + bgp: + Enforce IPv4 BGP peering for the peer + + Subclass of AvdModel. + ipv4_acl_in: + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + Required + for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under + `wan_carriers`. + ipv4_acl_out: + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + static_routes: + Configure IPv4 static routes pointing to `peer_ip`. + + Subclass of AvdList with `StaticRoutesItem` + items. + qos_profile: QOS service profile. + wan_carrier: + The WAN carrier this interface is connected to. + This is used to infer the path-groups in which this + interface should be configured. + Unless the carrier is marked as 'trusted' under `wan_carriers`, + `ipv4_acl_in` is also required on all WAN interfaces. + wan_circuit_id: + The WAN circuit ID for this interface. + This is not rendered in the configuration but used for WAN + designs. + connected_to_pathfinder: For a WAN interface (`wan_carrier` is set), allow to disable the static tunnel towards Pathfinders. + cv_pathfinder_internet_exit: + PREVIEW: This key is in preview mode + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the interface in the final EOS configuration. + flow_tracking: + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + structured_config: + Custom structured config for the Ethernet interface. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): + """Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + L3Interfaces._item_type = L3InterfacesItem + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "platform": {"type": str}, + "mac_address": {"type": str}, + "system_mac_address": {"type": str}, + "serial_number": {"type": str}, + "rack": {"type": str}, + "mgmt_ip": {"type": str}, + "mgmt_gateway": {"type": str}, + "ipv6_mgmt_ip": {"type": str}, + "ipv6_mgmt_gateway": {"type": str}, + "mgmt_interface": {"type": str}, + "link_tracking": {"type": LinkTracking}, + "lacp_port_id_range": {"type": LacpPortIdRange}, + "always_configure_ip_routing": {"type": bool, "default": False}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "uplink_type": {"type": str}, + "uplink_ipv4_pool": {"type": str}, + "uplink_interfaces": {"type": UplinkInterfaces}, + "uplink_switch_interfaces": {"type": UplinkSwitchInterfaces}, + "uplink_switches": {"type": UplinkSwitches}, + "uplink_interface_speed": {"type": str}, + "uplink_switch_interface_speed": {"type": str}, + "uplink_mtu": {"type": int}, + "max_uplink_switches": {"type": int}, + "max_parallel_uplinks": {"type": int, "default": 1}, + "uplink_bfd": {"type": bool, "default": False}, + "uplink_native_vlan": {"type": int}, + "uplink_ptp": {"type": UplinkPtp}, + "uplink_macsec": {"type": UplinkMacsec}, + "uplink_port_channel_id": {"type": int}, + "uplink_switch_port_channel_id": {"type": int}, + "uplink_structured_config": {"type": dict}, + "mlag_port_channel_structured_config": {"type": MlagPortChannelStructuredConfig}, + "mlag_peer_vlan_structured_config": {"type": MlagPeerVlanStructuredConfig}, + "mlag_peer_l3_vlan_structured_config": {"type": MlagPeerL3VlanStructuredConfig}, + "short_esi": {"type": str}, + "isis_system_id_prefix": {"type": str}, + "isis_maximum_paths": {"type": int}, + "is_type": {"type": str}, + "node_sid_base": {"type": int, "default": 0}, + "loopback_ipv4_pool": {"type": str}, + "loopback_ipv4_address": {"type": str}, + "vtep_loopback_ipv4_pool": {"type": str}, + "vtep_loopback_ipv4_address": {"type": str}, + "loopback_ipv4_offset": {"type": int, "default": 0}, + "loopback_ipv6_pool": {"type": str}, + "loopback_ipv6_offset": {"type": int, "default": 0}, + "vtep": {"type": bool}, + "vtep_loopback": {"type": str}, + "bgp_as": {"type": str}, + "bgp_defaults": {"type": BgpDefaults}, + "evpn_role": {"type": str}, + "evpn_route_servers": {"type": EvpnRouteServers}, + "evpn_services_l2_only": {"type": bool, "default": False}, + "filter": {"type": Filter}, + "igmp_snooping_enabled": {"type": bool}, + "evpn_gateway": {"type": EvpnGateway}, + "ipvpn_gateway": {"type": IpvpnGateway}, + "mlag": {"type": bool, "default": True}, + "mlag_dual_primary_detection": {"type": bool, "default": False}, + "mlag_ibgp_origin_incomplete": {"type": bool, "default": True}, + "mlag_interfaces": {"type": MlagInterfaces}, + "mlag_interfaces_speed": {"type": str}, + "mlag_peer_l3_vlan": {"type": int, "default": 4093}, + "mlag_peer_l3_ipv4_pool": {"type": str}, + "mlag_peer_vlan": {"type": int, "default": 4094}, + "mlag_peer_link_allowed_vlans": {"type": str}, + "mlag_peer_address_family": {"type": str, "default": "ipv4"}, + "mlag_peer_ipv4_pool": {"type": str}, + "mlag_peer_ipv6_pool": {"type": str}, + "mlag_port_channel_id": {"type": int}, + "mlag_domain_id": {"type": str}, + "spanning_tree_mode": {"type": str}, + "spanning_tree_priority": {"type": int, "default": 32768}, + "spanning_tree_root_super": {"type": bool, "default": False}, + "virtual_router_mac_address": {"type": str}, + "inband_mgmt_interface": {"type": str}, + "inband_mgmt_vlan": {"type": int, "default": 4092}, + "inband_mgmt_subnet": {"type": str}, + "inband_mgmt_ip": {"type": str}, + "inband_mgmt_gateway": {"type": str}, + "inband_mgmt_ipv6_address": {"type": str}, + "inband_mgmt_ipv6_subnet": {"type": str}, + "inband_mgmt_ipv6_gateway": {"type": str}, + "inband_mgmt_description": {"type": str, "default": "Inband Management"}, + "inband_mgmt_vlan_name": {"type": str, "default": "INBAND_MGMT"}, + "inband_mgmt_vrf": {"type": str, "default": "default"}, + "inband_mgmt_mtu": {"type": int, "default": 1500}, + "inband_ztp": {"type": bool, "default": False}, + "inband_ztp_lacp_fallback_delay": {"type": int, "default": 30}, + "mpls_overlay_role": {"type": str}, + "overlay_address_families": {"type": OverlayAddressFamilies}, + "mpls_route_reflectors": {"type": MplsRouteReflectors}, + "bgp_cluster_id": {"type": str}, + "ptp": {"type": Ptp}, + "wan_role": {"type": str}, + "cv_pathfinder_transit_mode": {"type": str}, + "cv_pathfinder_region": {"type": str}, + "cv_pathfinder_site": {"type": str}, + "wan_ha": {"type": WanHa}, + "dps_mss_ipv4": {"type": str, "default": "auto"}, + "l3_interfaces": {"type": L3Interfaces}, + "data_plane_cpu_allocation_max": {"type": int}, + "flow_tracker_type": {"type": str}, + "_custom_data": {"type": dict}, + } + id: int | None + """Unique identifier used for IP addressing and other algorithms.""" + platform: str | None + """Arista platform family.""" + mac_address: str | None + """Leverage to document management interface mac address.""" + system_mac_address: str | None + """ + System MAC Address in this following format: "xx:xx:xx:xx:xx:xx". + Set to the same MAC address as + available in "show version" on the device. + "system_mac_address" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + """ + serial_number: str | None + """ + Set to the Serial Number of the device. + Only used for documentation purpose in the fabric + documentation and part of the structured_config. + "serial_number" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + """ + rack: str | None + """Rack that the switch is located in (only used in snmp_settings location).""" + mgmt_ip: str | None + """Node management interface IPv4 address.""" + mgmt_gateway: str | None + """ + This key sets the management gateway for the device. It takes precedence over the global + `mgmt_gateway`. + """ + ipv6_mgmt_ip: str | None + """Node management interface IPv6 address.""" + ipv6_mgmt_gateway: str | None + """ + This key sets the ipv6 management gateway for the device. It takes precedence over the global + `ipv6_mgmt_gateway`. + """ + mgmt_interface: str | None + """ + Management Interface Name. + Default -> platform_management_interface -> mgmt_interface -> + "Management1". + """ + link_tracking: LinkTracking + """ + This configures the Link Tracking Group on a switch as well as adds the p2p-uplinks of the switch as + the upstream interfaces. + Useful in EVPN multhoming designs. + + + Subclass of AvdModel. + """ + lacp_port_id_range: LacpPortIdRange + """ + This will generate the "lacp port-id range", "begin" and "end" values based on node "id" and the + number of nodes in the "node_group". + Unique LACP port-id ranges are recommended for EVPN Multihoming + designs. + + + Subclass of AvdModel. + """ + always_configure_ip_routing: bool + """ + Force configuration of "ip routing" even on L2 devices. + Use this to retain behavior of AVD versions + below 4.0.0. + + Default value: `False` + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the root level of the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + """ + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None + """ + Override the default `uplink_type` set at the `node_type_key` level. + `uplink_type` must be "p2p" if + `vtep` or `underlay_router` is true for the `node_type_key` definition. + """ + uplink_ipv4_pool: str | None + """IPv4 subnet to use to connect to uplink switches.""" + uplink_interfaces: UplinkInterfaces + """ + Local uplink interfaces. + Each list item supports range syntax that can be expanded into a list of + interfaces. + If uplink_interfaces is not defined, platform-specific defaults (defined under + default_interfaces) will be used instead. + Please note that default_interfaces are not defined by + default, you should define these yourself. + + + Subclass of AvdList with `str` items. + """ + uplink_switch_interfaces: UplinkSwitchInterfaces + """ + Interfaces located on uplink switches. + + Subclass of AvdList with `str` items. + """ + uplink_switches: UplinkSwitches + """Subclass of AvdList with `str` items.""" + uplink_interface_speed: str | None + """ + Set point-to-Point interface speed and will apply to uplink interfaces on both ends. + (Uplink switch + interface speed can be overridden with `uplink_switch_interface_speed`). + Speed should be set in the + format `` or `forced ` or `auto `. + """ + uplink_switch_interface_speed: str | None + """ + 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: int | None + """Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting.""" + max_uplink_switches: int | None + """ + 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: 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 + """ + Enable bfd on uplink interfaces. + + Default value: `False` + """ + uplink_native_vlan: int | None + """ + 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: UplinkPtp + """ + Enable PTP on all infrastructure links. + + Subclass of AvdModel. + """ + uplink_macsec: UplinkMacsec + """ + Enable MacSec on all uplinks. + + Subclass of AvdModel. + """ + uplink_port_channel_id: int | None + """ + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink Port-channel + ID will be set to the number of the lowest member interface defined under `uplink_interfaces`. + For + example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ Eth11/1, Eth22/1 ] -> ID 111 + For + MLAG port-channels ID will be based on the lowest member interface on the first MLAG switch. + This + option overrides the default behavior and statically sets the local Port-channel ID. + Note! Make sure + the ID is unique and does not overlap with autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between 1 and 2000 and both MLAG switches must have the same + value. + """ + uplink_switch_port_channel_id: int | None + """ + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink switch Port- + channel ID will be set to the number of the first interface defined under + `uplink_switch_interfaces`. + For example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ + Eth11/1, Eth22/1 ] -> ID 111 + For MLAG port-channels ID will be based on the lowest member interface + on the first MLAG switch. + This option overrides the default behavior and statically sets the Port- + channel ID on the uplink switch. + Note! Make sure the ID is unique and does not overlap with + autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between + 1 and 2000 and both MLAG switches must have the same value. + """ + uplink_structured_config: dict + """ + Custom structured config applied to "uplink_interfaces", and "uplink_switch_interfaces". + When + uplink_type == "p2p", custom structured config added under ethernet_interfaces.[name=] + for eos_cli_config_gen overrides the settings on the ethernet interface level. + When uplink_type == + "port-channel", custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen overrides the settings on the port-channel interface level. + "uplink_structured_config" is applied after "structured_config", so it can override + "structured_config" defined on node-level. + Note! The content of this dictionary is _not_ validated + by the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + """ + mlag_port_channel_structured_config: MlagPortChannelStructuredConfig + """ + Custom structured config applied to MLAG peer link port-channel id. + Added under + port_channel_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the + port-channel interface level. + "mlag_port_channel_structured_config" is applied after + "structured_config", so it can override "structured_config" defined on node-level. + + + Subclass of + AvdModel. + """ + mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig + """ + Custom structured config applied to MLAG Peer Link (control link) SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_vlan_structured_config" is applied after "structured_config", so it can + override "structured_config" defined on node-level. + + + Subclass of AvdModel. + """ + mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig + """ + Custom structured config applied to MLAG underlay L3 peering SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_l3_vlan_structured_config" is applied after "structured_config", so it + can override "structured_config" defined on node-level. + + + Subclass of AvdModel. + """ + short_esi: str | None + """ + short_esi only valid for l2leaf devices using port-channel uplink. + Setting short_esi to "auto" + generates the short_esi automatically using a hash of configuration elements. + < 0000:0000:0000 | + auto >. + """ + isis_system_id_prefix: str | None + """(4.4 hexadecimal).""" + isis_maximum_paths: int | None + """Number of path to configure in ECMP for ISIS.""" + is_type: Literal["level-1-2", "level-1", "level-2"] | None + """Overrides `isis_default_is_type`.""" + node_sid_base: int + """ + Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID. + + Default value: `0` + """ + loopback_ipv4_pool: str | None + """IPv4 subnet for Loopback0 allocation.""" + loopback_ipv4_address: str | None + """ + IPv4 address without mask for Loopback0. + When set, it takes precedence over `loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not catch duplicates. + """ + vtep_loopback_ipv4_pool: str | None + """IPv4 subnet for VTEP-Loopback allocation.""" + vtep_loopback_ipv4_address: str | None + """ + IPv4 address without mask for VTEP-Loopback. + When set, it takes precedence over + `vtep_loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not + catch duplicates. + """ + loopback_ipv4_offset: int + """ + Offset all assigned loopback IP addresses. + Required when the < loopback_ipv4_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid over-lapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv4_offset: < total # spine switches > or vice versa. + + Default value: `0` + """ + loopback_ipv6_pool: str | None + """IPv6 subnet for Loopback0 allocation.""" + loopback_ipv6_offset: int + """ + Offset all assigned loopback IPv6 addresses. + Required when the < loopback_ipv6_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid overlapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv6_offset: < total # spine switches > or vice versa. + + Default value: `0` + """ + vtep: bool | None + """ + Node is configured as a VTEP when applicable based on 'overlay_routing_protocol'. + Overrides VTEP + setting inherited from node_type_keys. + """ + vtep_loopback: str | None + """Set VXLAN source interface.""" + bgp_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + Required with eBGP. + """ + bgp_defaults: BgpDefaults + """ + List of EOS commands to apply to BGP daemon. + + Subclass of AvdList with `str` items. + """ + evpn_role: Literal["client", "server", "none"] | None + """ + Acting role in EVPN control plane. + Default is set in node_type definition from node_type_keys. + """ + evpn_route_servers: EvpnRouteServers + """ + List of nodes acting as EVPN Route-Servers / Route-Reflectors. + + Subclass of AvdList with `str` + items. + """ + evpn_services_l2_only: bool + """ + Possibility to prevent configuration of Tenant VRFs and SVIs. + Override node definition + "network_services_l3" from node_type_keys. + This allows support for centralized routing. + + Default value: `False` + """ + filter: Filter + """ + Filter L3 and L2 network services based on tenant and tags (and operation filter). + If filter is not + defined it will default to all. + + + Subclass of AvdModel. + """ + igmp_snooping_enabled: bool | None + """Activate or deactivate IGMP snooping on device level.""" + evpn_gateway: EvpnGateway + """ + Node is acting as EVPN Multi-Domain Gateway. + New BGP peer-group is generated between EVPN GWs in + different domains or between GWs and Route Servers. + Name can be changed under + "bgp_peer_groups.evpn_overlay_core" variable. + L3 rechability for different EVPN GWs must be already + in place, it is recommended to use DCI & L3 Edge if Route Servers and GWs are not defined under the + same Ansible inventory. + + + Subclass of AvdModel. + """ + ipvpn_gateway: IpvpnGateway + """ + Node is acting as IP-VPN Gateway for EVPN to MPLS-IP-VPN Interworking. The BGP peer group used for + this is "bgp_peer_groups.ipvpn_gateway_peers". + L3 Reachability is required for this to work, the + preferred method to establish underlay connectivity is to use core_interfaces. + + + Subclass of + AvdModel. + """ + mlag: bool + """ + Enable / Disable auto MLAG, when two nodes are defined in node group. + + Default value: `True` + """ + mlag_dual_primary_detection: bool + """ + Enable / Disable MLAG dual primary detection. + + Default value: `False` + """ + mlag_ibgp_origin_incomplete: bool + """ + Set origin of routes received from MLAG iBGP peer to incomplete. + The purpose is to optimize routing + for leaf loopbacks from spine perspective and + avoid suboptimal routing via peerlink for control + plane traffic. + + Default value: `True` + """ + mlag_interfaces: MlagInterfaces + """ + Each list item supports range syntax that can be expanded into a list of interfaces. + Required when + MLAG leafs are present in the topology. + + + Subclass of AvdList with `str` items. + """ + mlag_interfaces_speed: str | None + """ + Set MLAG interface speed. + Speed should be set in the format `` or `forced + ` or `auto `. + """ + mlag_peer_l3_vlan: int + """ + Underlay L3 peering SVI interface id. + If set to 0 or the same vlan as mlag_peer_vlan, the + mlag_peer_vlan will be used for L3 peering. + + Default value: `4093` + """ + mlag_peer_l3_ipv4_pool: str | None + """ + IP address pool used for MLAG underlay L3 peering. IP is derived from the node id. + Required when + MLAG leafs present in topology and they are using a separate L3 peering VLAN. + """ + mlag_peer_vlan: int + """ + MLAG Peer Link (control link) SVI interface id. + + Default value: `4094` + """ + mlag_peer_link_allowed_vlans: str | None + mlag_peer_address_family: Literal["ipv4", "ipv6"] + """ + IP address family used to establish MLAG Peer Link (control link). + `ipv6` requires EOS version + 4.31.1F or higher. + Note: `ipv6` is not supported in combination with a common MLAG peer link VLAN + (ex. `mlag_peer_l3_vlan` set to 4094). + + Default value: `"ipv4"` + """ + mlag_peer_ipv4_pool: str | None + """ + IPv4 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv4` (default). + """ + mlag_peer_ipv6_pool: str | None + """ + IPv6 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv6`. + """ + mlag_port_channel_id: int | None + """ + If not set, the mlag port-channel id is generated based on the digits of the first interface present + in 'mlag_interfaces'. + Valid port-channel id numbers are < 1-2000 > for EOS < 4.25.0F and < 1 - + 999999 > for EOS >= 4.25.0F. + """ + mlag_domain_id: str | None + """MLAG Domain ID. If not set the node group name (Set with "group" key) will be used.""" + spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None + spanning_tree_priority: int + """ + Spanning-tree priority configured for the selected mode. + For `rapid-pvst` the priority can also be + set per VLAN under network services. + + Default value: `32768` + """ + spanning_tree_root_super: bool + """Default value: `False`""" + virtual_router_mac_address: str | None + """Virtual router mac address for anycast gateway.""" + inband_mgmt_interface: str | None + """ + Pointer to interface used for inband management. + All configuration must be done using other data + models like network services or structured_config. + 'inband_mgmt_interface' is only used to refer to + this interface as source in various management protocol settings (future feature). + + On L2 switches, + this defaults to Vlan if either 'inband_mgmt_subnet' or 'inband_mgmt_ip' is set. + """ + inband_mgmt_vlan: int + """ + VLAN number used for inband management on L2 switches (switches using port-channel trunks as + uplinks). + When using 'inband_mgmt_subnet' the VLAN and SVIs will be created automatically on this + switch as well as all 'uplink_switches'. + When using 'inband_mgmt_ip' the VLAN and SVI will only be + created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be + created using network services data models. + + Default value: `4092` + """ + inband_mgmt_subnet: str | None + """ + Optional IP subnet assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ip virtual-router" and host-route injection based on + ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + + 3 + + GW on l2leafs : + 1 + Assign range larger than total l2leafs + 5 + Setting is ignored if 'inband_mgmt_ip' is set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + """ + inband_mgmt_ip: str | None + """ + IP address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_subnet', hence all behavior of 'inband_mgmt_subnet' is removed. + + If this is set the + VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN and SVI on + the parent switches must be created using network services data models. + + This setting is applicable + to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_gateway: str | None + """ + Default gateway configured in the 'inband_mgmt_vrf' when using 'inband_mgmt_ip'. Otherwise gateway + is derived from 'inband_mgmt_subnet' if set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_address: str | None + """ + IPv6 address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_ipv6_subnet', hence the configuration of 'inband_mgmt_ipv6_subnet' is ignored. + + If this + is set the VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN + and SVI on the parent switches must be created using network services data models. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_subnet: str | None + """ + Optional IPv6 prefix assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ipv6 virtual-router" and host-route injection based + on ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN + extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + 3 + + GW on l2leafs : + 1 + Assign range larger than + total l2leafs + 5 + + Setting is ignored if 'inband_mgmt_ipv6_address' is set. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_gateway: str | None + """ + Default gateway configured in the 'inband_mgmt_vrf'. + Used when `inband_mgmt_ipv6_address` is set. + Ignored when 'inband_mgmt_ipv6_subnet' is set (first IP in subnet used as gateway). + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_description: str + """ + Description configured on the Inband Management SVI. + + This setting is only applied on the devices + where it is set, it does not automatically affect any parent/child devices configuration, so it must + be set on each applicable node/node-group/node-type as needed. + + Default value: `"Inband Management"` + """ + inband_mgmt_vlan_name: str + """ + Name configured on the Inband Management VLAN. + This setting is only applied on the devices where it + is set, it does not automatically affect any parent/child devices configuration, so it must be set + on each applicable node/node-group/node-type as needed. + + Default value: `"INBAND_MGMT"` + """ + inband_mgmt_vrf: str + """ + VRF configured on the Inband Management Interface. + The VRF is created if not already created by + other means. + This setting is only applied on the devices where it is set, it does not automatically + affect any parent/child devices configuration, so it must be set on each applicable node/node- + group/node-type as needed. + + Default value: `"default"` + """ + inband_mgmt_mtu: int + """ + MTU configured on the Inband Management Interface. + This setting is only applied on the devices where + it is set, it does not automatically affect any parent/child devices configuration, so it must be + set on each applicable node/node-group/node-type as needed. + + Default value: `1500` + """ + inband_ztp: bool + """ + Enable to configure upstream device with proper configuration to allow downstream devices to be + Zero-Touch-Provisioned over the uplink interfaces. + For L2 devices this setting also requires that + the `inband_mgmt_vlan` is set for the node. + + PREVIEW: Support for L3 devices is marked as "preview", + meaning the data models or generated configuration can change at any time. + + Default value: `False` + """ + inband_ztp_lacp_fallback_delay: int + """ + Set the LACP fallback timeout of the upstream device's port-channel towards the downstream inband + ZTP node. + This setting also requires that `inband_ztp` is set for the node. + + Default value: `30` + """ + mpls_overlay_role: Literal["client", "server", "none"] | None + """ + Set the default mpls overlay role. + Acting role in overlay control plane. + """ + overlay_address_families: OverlayAddressFamilies + """ + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + """ + mpls_route_reflectors: MplsRouteReflectors + """ + List of inventory hostname acting as MPLS route-reflectors. + + Subclass of AvdList with `str` items. + """ + bgp_cluster_id: str | None + """Set BGP cluster id.""" + ptp: Ptp + """Subclass of AvdModel.""" + wan_role: Literal["client", "server"] | None + """ + Override the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + """ + cv_pathfinder_transit_mode: Literal["region", "zone"] | None + """ + Configure the transit mode for a WAN client for CV Pathfinder designs + only when the `wan_mode` root + key is set to `cv_pathfinder`. + + 'zone' is currently not supported. + """ + cv_pathfinder_region: str | None + """ + The CV Pathfinder region name. + This key is required for WAN routers but optional for pathfinders. + The region name must be defined under 'cv_pathfinder_regions'. + """ + cv_pathfinder_site: str | None + """ + The CV Pathfinder site name. + This key is required for WAN routers but optional for pathfinders. + For + WAN routers and pathfinders with `cv_pathfinder_region`, the site name must be defined for the + relevant region under 'cv_pathfinder_regions'. + For pathfinders without `cv_pathfinder_region` set, + the site must be defined under `cv_pathfinder_global_sites`. + """ + wan_ha: WanHa + """ + PREVIEW: This key is currently not supported + + The key is supported only if `wan_mode` == `cv- + pathfinder`. + AutoVPN support is still to be determined. + + Maximum 2 devices supported by group for + HA. + + Subclass of AvdModel. + """ + dps_mss_ipv4: str + """ + IPv4 MSS value configured under "router path-selection" on WAN Devices. + + Default value: `"auto"` + """ + l3_interfaces: L3Interfaces + """ + L3 Interfaces to configure on the node. + Used to define the node for WAN interfaces when + `wan_carrier` is set. + + Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is + `name` (`str`). + """ + data_plane_cpu_allocation_max: int | None + """ + Set the maximum number of CPU used for the data plane. + This setting is useful on virtual Route + Reflectors and Pathfinders where more CPU cores should be allocated for control plane. + """ + flow_tracker_type: Literal["sampled", "hardware"] | None + """ + Set the flow tracker type. + Override the `default_flow_tracker_type`` set at the `node_type_key` + level. + `default_flow_tracker_type` default value is `sampled`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | None | UndefinedType = Undefined, + platform: str | None | UndefinedType = Undefined, + mac_address: str | None | UndefinedType = Undefined, + system_mac_address: str | None | UndefinedType = Undefined, + serial_number: str | None | UndefinedType = Undefined, + rack: str | None | UndefinedType = Undefined, + mgmt_ip: str | None | UndefinedType = Undefined, + mgmt_gateway: str | None | UndefinedType = Undefined, + ipv6_mgmt_ip: str | None | UndefinedType = Undefined, + ipv6_mgmt_gateway: str | None | UndefinedType = Undefined, + mgmt_interface: str | None | UndefinedType = Undefined, + link_tracking: LinkTracking | UndefinedType = Undefined, + lacp_port_id_range: LacpPortIdRange | UndefinedType = Undefined, + always_configure_ip_routing: bool | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None | UndefinedType = Undefined, + uplink_ipv4_pool: str | None | UndefinedType = Undefined, + uplink_interfaces: UplinkInterfaces | UndefinedType = Undefined, + uplink_switch_interfaces: UplinkSwitchInterfaces | UndefinedType = Undefined, + uplink_switches: UplinkSwitches | UndefinedType = Undefined, + uplink_interface_speed: str | None | UndefinedType = Undefined, + 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 | UndefinedType = Undefined, + uplink_bfd: bool | UndefinedType = Undefined, + uplink_native_vlan: int | None | UndefinedType = Undefined, + uplink_ptp: UplinkPtp | UndefinedType = Undefined, + uplink_macsec: UplinkMacsec | UndefinedType = Undefined, + uplink_port_channel_id: int | None | UndefinedType = Undefined, + uplink_switch_port_channel_id: int | None | UndefinedType = Undefined, + uplink_structured_config: dict | UndefinedType = Undefined, + mlag_port_channel_structured_config: MlagPortChannelStructuredConfig | UndefinedType = Undefined, + mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig | UndefinedType = Undefined, + mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig | UndefinedType = Undefined, + short_esi: str | None | UndefinedType = Undefined, + isis_system_id_prefix: str | None | UndefinedType = Undefined, + isis_maximum_paths: int | None | UndefinedType = Undefined, + is_type: Literal["level-1-2", "level-1", "level-2"] | None | UndefinedType = Undefined, + node_sid_base: int | UndefinedType = Undefined, + loopback_ipv4_pool: str | None | UndefinedType = Undefined, + loopback_ipv4_address: str | None | UndefinedType = Undefined, + vtep_loopback_ipv4_pool: str | None | UndefinedType = Undefined, + vtep_loopback_ipv4_address: str | None | UndefinedType = Undefined, + loopback_ipv4_offset: int | UndefinedType = Undefined, + loopback_ipv6_pool: str | None | UndefinedType = Undefined, + loopback_ipv6_offset: int | UndefinedType = Undefined, + vtep: bool | None | UndefinedType = Undefined, + vtep_loopback: str | None | UndefinedType = Undefined, + bgp_as: str | None | UndefinedType = Undefined, + bgp_defaults: BgpDefaults | UndefinedType = Undefined, + evpn_role: Literal["client", "server", "none"] | None | UndefinedType = Undefined, + evpn_route_servers: EvpnRouteServers | UndefinedType = Undefined, + evpn_services_l2_only: bool | UndefinedType = Undefined, + filter: Filter | UndefinedType = Undefined, + igmp_snooping_enabled: bool | None | UndefinedType = Undefined, + evpn_gateway: EvpnGateway | UndefinedType = Undefined, + ipvpn_gateway: IpvpnGateway | UndefinedType = Undefined, + mlag: bool | UndefinedType = Undefined, + mlag_dual_primary_detection: bool | UndefinedType = Undefined, + mlag_ibgp_origin_incomplete: bool | UndefinedType = Undefined, + mlag_interfaces: MlagInterfaces | UndefinedType = Undefined, + mlag_interfaces_speed: str | None | UndefinedType = Undefined, + mlag_peer_l3_vlan: int | UndefinedType = Undefined, + mlag_peer_l3_ipv4_pool: str | None | UndefinedType = Undefined, + mlag_peer_vlan: int | UndefinedType = Undefined, + mlag_peer_link_allowed_vlans: str | None | UndefinedType = Undefined, + mlag_peer_address_family: Literal["ipv4", "ipv6"] | UndefinedType = Undefined, + mlag_peer_ipv4_pool: str | None | UndefinedType = Undefined, + mlag_peer_ipv6_pool: str | None | UndefinedType = Undefined, + mlag_port_channel_id: int | None | UndefinedType = Undefined, + mlag_domain_id: str | None | UndefinedType = Undefined, + spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None | UndefinedType = Undefined, + spanning_tree_priority: int | UndefinedType = Undefined, + spanning_tree_root_super: bool | UndefinedType = Undefined, + virtual_router_mac_address: str | None | UndefinedType = Undefined, + inband_mgmt_interface: str | None | UndefinedType = Undefined, + inband_mgmt_vlan: int | UndefinedType = Undefined, + inband_mgmt_subnet: str | None | UndefinedType = Undefined, + inband_mgmt_ip: str | None | UndefinedType = Undefined, + inband_mgmt_gateway: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_address: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_subnet: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_gateway: str | None | UndefinedType = Undefined, + inband_mgmt_description: str | UndefinedType = Undefined, + inband_mgmt_vlan_name: str | UndefinedType = Undefined, + inband_mgmt_vrf: str | UndefinedType = Undefined, + inband_mgmt_mtu: int | UndefinedType = Undefined, + inband_ztp: bool | UndefinedType = Undefined, + inband_ztp_lacp_fallback_delay: int | UndefinedType = Undefined, + mpls_overlay_role: Literal["client", "server", "none"] | None | UndefinedType = Undefined, + overlay_address_families: OverlayAddressFamilies | UndefinedType = Undefined, + mpls_route_reflectors: MplsRouteReflectors | UndefinedType = Undefined, + bgp_cluster_id: str | None | UndefinedType = Undefined, + ptp: Ptp | UndefinedType = Undefined, + wan_role: Literal["client", "server"] | None | UndefinedType = Undefined, + cv_pathfinder_transit_mode: Literal["region", "zone"] | None | UndefinedType = Undefined, + cv_pathfinder_region: str | None | UndefinedType = Undefined, + cv_pathfinder_site: str | None | UndefinedType = Undefined, + wan_ha: WanHa | UndefinedType = Undefined, + dps_mss_ipv4: str | UndefinedType = Undefined, + l3_interfaces: L3Interfaces | UndefinedType = Undefined, + data_plane_cpu_allocation_max: int | None | UndefinedType = Undefined, + flow_tracker_type: Literal["sampled", "hardware"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Defaults. + + + Subclass of AvdModel. + + Args: + id: Unique identifier used for IP addressing and other algorithms. + platform: Arista platform family. + mac_address: Leverage to document management interface mac address. + system_mac_address: + System MAC Address in this following format: "xx:xx:xx:xx:xx:xx". + Set to the same MAC address as + available in "show version" on the device. + "system_mac_address" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + serial_number: + Set to the Serial Number of the device. + Only used for documentation purpose in the fabric + documentation and part of the structured_config. + "serial_number" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + rack: Rack that the switch is located in (only used in snmp_settings location). + mgmt_ip: Node management interface IPv4 address. + mgmt_gateway: + This key sets the management gateway for the device. It takes precedence over the global + `mgmt_gateway`. + ipv6_mgmt_ip: Node management interface IPv6 address. + ipv6_mgmt_gateway: + This key sets the ipv6 management gateway for the device. It takes precedence over the global + `ipv6_mgmt_gateway`. + mgmt_interface: + Management Interface Name. + Default -> platform_management_interface -> mgmt_interface -> + "Management1". + link_tracking: + This configures the Link Tracking Group on a switch as well as adds the p2p-uplinks of the switch as + the upstream interfaces. + Useful in EVPN multhoming designs. + + + Subclass of AvdModel. + lacp_port_id_range: + This will generate the "lacp port-id range", "begin" and "end" values based on node "id" and the + number of nodes in the "node_group". + Unique LACP port-id ranges are recommended for EVPN Multihoming + designs. + + + Subclass of AvdModel. + always_configure_ip_routing: + Force configuration of "ip routing" even on L2 devices. + Use this to retain behavior of AVD versions + below 4.0.0. + raw_eos_cli: EOS CLI rendered directly on the root level of the final EOS configuration. + structured_config: + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + uplink_type: + Override the default `uplink_type` set at the `node_type_key` level. + `uplink_type` must be "p2p" if + `vtep` or `underlay_router` is true for the `node_type_key` definition. + uplink_ipv4_pool: IPv4 subnet to use to connect to uplink switches. + uplink_interfaces: + Local uplink interfaces. + Each list item supports range syntax that can be expanded into a list of + interfaces. + If uplink_interfaces is not defined, platform-specific defaults (defined under + default_interfaces) will be used instead. + Please note that default_interfaces are not defined by + default, you should define these yourself. + + + Subclass of AvdList with `str` items. + uplink_switch_interfaces: + Interfaces located on uplink switches. + + Subclass of AvdList with `str` items. + uplink_switches: Subclass of AvdList with `str` items. + uplink_interface_speed: + Set point-to-Point interface speed and will apply to uplink interfaces on both ends. + (Uplink switch + interface speed can be overridden with `uplink_switch_interface_speed`). + Speed should be set in the + format `` or `forced ` or `auto `. + uplink_switch_interface_speed: + 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: Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting. + max_uplink_switches: + 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: + 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: Enable bfd on uplink interfaces. + uplink_native_vlan: + 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: + Enable PTP on all infrastructure links. + + Subclass of AvdModel. + uplink_macsec: + Enable MacSec on all uplinks. + + Subclass of AvdModel. + uplink_port_channel_id: + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink Port-channel + ID will be set to the number of the lowest member interface defined under `uplink_interfaces`. + For + example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ Eth11/1, Eth22/1 ] -> ID 111 + For + MLAG port-channels ID will be based on the lowest member interface on the first MLAG switch. + This + option overrides the default behavior and statically sets the local Port-channel ID. + Note! Make sure + the ID is unique and does not overlap with autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between 1 and 2000 and both MLAG switches must have the same + value. + uplink_switch_port_channel_id: + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink switch Port- + channel ID will be set to the number of the first interface defined under + `uplink_switch_interfaces`. + For example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ + Eth11/1, Eth22/1 ] -> ID 111 + For MLAG port-channels ID will be based on the lowest member interface + on the first MLAG switch. + This option overrides the default behavior and statically sets the Port- + channel ID on the uplink switch. + Note! Make sure the ID is unique and does not overlap with + autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between + 1 and 2000 and both MLAG switches must have the same value. + uplink_structured_config: + Custom structured config applied to "uplink_interfaces", and "uplink_switch_interfaces". + When + uplink_type == "p2p", custom structured config added under ethernet_interfaces.[name=] + for eos_cli_config_gen overrides the settings on the ethernet interface level. + When uplink_type == + "port-channel", custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen overrides the settings on the port-channel interface level. + "uplink_structured_config" is applied after "structured_config", so it can override + "structured_config" defined on node-level. + Note! The content of this dictionary is _not_ validated + by the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + mlag_port_channel_structured_config: + Custom structured config applied to MLAG peer link port-channel id. + Added under + port_channel_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the + port-channel interface level. + "mlag_port_channel_structured_config" is applied after + "structured_config", so it can override "structured_config" defined on node-level. + + + Subclass of + AvdModel. + mlag_peer_vlan_structured_config: + Custom structured config applied to MLAG Peer Link (control link) SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_vlan_structured_config" is applied after "structured_config", so it can + override "structured_config" defined on node-level. + + + Subclass of AvdModel. + mlag_peer_l3_vlan_structured_config: + Custom structured config applied to MLAG underlay L3 peering SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_l3_vlan_structured_config" is applied after "structured_config", so it + can override "structured_config" defined on node-level. + + + Subclass of AvdModel. + short_esi: + short_esi only valid for l2leaf devices using port-channel uplink. + Setting short_esi to "auto" + generates the short_esi automatically using a hash of configuration elements. + < 0000:0000:0000 | + auto >. + isis_system_id_prefix: (4.4 hexadecimal). + isis_maximum_paths: Number of path to configure in ECMP for ISIS. + is_type: Overrides `isis_default_is_type`. + node_sid_base: Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID. + loopback_ipv4_pool: IPv4 subnet for Loopback0 allocation. + loopback_ipv4_address: + IPv4 address without mask for Loopback0. + When set, it takes precedence over `loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not catch duplicates. + vtep_loopback_ipv4_pool: IPv4 subnet for VTEP-Loopback allocation. + vtep_loopback_ipv4_address: + IPv4 address without mask for VTEP-Loopback. + When set, it takes precedence over + `vtep_loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not + catch duplicates. + loopback_ipv4_offset: + Offset all assigned loopback IP addresses. + Required when the < loopback_ipv4_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid over-lapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv4_offset: < total # spine switches > or vice versa. + loopback_ipv6_pool: IPv6 subnet for Loopback0 allocation. + loopback_ipv6_offset: + Offset all assigned loopback IPv6 addresses. + Required when the < loopback_ipv6_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid overlapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv6_offset: < total # spine switches > or vice versa. + vtep: + Node is configured as a VTEP when applicable based on 'overlay_routing_protocol'. + Overrides VTEP + setting inherited from node_type_keys. + vtep_loopback: Set VXLAN source interface. + bgp_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + Required with eBGP. + bgp_defaults: + List of EOS commands to apply to BGP daemon. + + Subclass of AvdList with `str` items. + evpn_role: + Acting role in EVPN control plane. + Default is set in node_type definition from node_type_keys. + evpn_route_servers: + List of nodes acting as EVPN Route-Servers / Route-Reflectors. + + Subclass of AvdList with `str` + items. + evpn_services_l2_only: + Possibility to prevent configuration of Tenant VRFs and SVIs. + Override node definition + "network_services_l3" from node_type_keys. + This allows support for centralized routing. + filter: + Filter L3 and L2 network services based on tenant and tags (and operation filter). + If filter is not + defined it will default to all. + + + Subclass of AvdModel. + igmp_snooping_enabled: Activate or deactivate IGMP snooping on device level. + evpn_gateway: + Node is acting as EVPN Multi-Domain Gateway. + New BGP peer-group is generated between EVPN GWs in + different domains or between GWs and Route Servers. + Name can be changed under + "bgp_peer_groups.evpn_overlay_core" variable. + L3 rechability for different EVPN GWs must be already + in place, it is recommended to use DCI & L3 Edge if Route Servers and GWs are not defined under the + same Ansible inventory. + + + Subclass of AvdModel. + ipvpn_gateway: + Node is acting as IP-VPN Gateway for EVPN to MPLS-IP-VPN Interworking. The BGP peer group used for + this is "bgp_peer_groups.ipvpn_gateway_peers". + L3 Reachability is required for this to work, the + preferred method to establish underlay connectivity is to use core_interfaces. + + + Subclass of + AvdModel. + mlag: Enable / Disable auto MLAG, when two nodes are defined in node group. + mlag_dual_primary_detection: Enable / Disable MLAG dual primary detection. + mlag_ibgp_origin_incomplete: + Set origin of routes received from MLAG iBGP peer to incomplete. + The purpose is to optimize routing + for leaf loopbacks from spine perspective and + avoid suboptimal routing via peerlink for control + plane traffic. + mlag_interfaces: + Each list item supports range syntax that can be expanded into a list of interfaces. + Required when + MLAG leafs are present in the topology. + + + Subclass of AvdList with `str` items. + mlag_interfaces_speed: + Set MLAG interface speed. + Speed should be set in the format `` or `forced + ` or `auto `. + mlag_peer_l3_vlan: + Underlay L3 peering SVI interface id. + If set to 0 or the same vlan as mlag_peer_vlan, the + mlag_peer_vlan will be used for L3 peering. + mlag_peer_l3_ipv4_pool: + IP address pool used for MLAG underlay L3 peering. IP is derived from the node id. + Required when + MLAG leafs present in topology and they are using a separate L3 peering VLAN. + mlag_peer_vlan: MLAG Peer Link (control link) SVI interface id. + mlag_peer_link_allowed_vlans: mlag_peer_link_allowed_vlans + mlag_peer_address_family: + IP address family used to establish MLAG Peer Link (control link). + `ipv6` requires EOS version + 4.31.1F or higher. + Note: `ipv6` is not supported in combination with a common MLAG peer link VLAN + (ex. `mlag_peer_l3_vlan` set to 4094). + mlag_peer_ipv4_pool: + IPv4 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv4` (default). + mlag_peer_ipv6_pool: + IPv6 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv6`. + mlag_port_channel_id: + If not set, the mlag port-channel id is generated based on the digits of the first interface present + in 'mlag_interfaces'. + Valid port-channel id numbers are < 1-2000 > for EOS < 4.25.0F and < 1 - + 999999 > for EOS >= 4.25.0F. + mlag_domain_id: MLAG Domain ID. If not set the node group name (Set with "group" key) will be used. + spanning_tree_mode: spanning_tree_mode + spanning_tree_priority: + Spanning-tree priority configured for the selected mode. + For `rapid-pvst` the priority can also be + set per VLAN under network services. + spanning_tree_root_super: spanning_tree_root_super + virtual_router_mac_address: Virtual router mac address for anycast gateway. + inband_mgmt_interface: + Pointer to interface used for inband management. + All configuration must be done using other data + models like network services or structured_config. + 'inband_mgmt_interface' is only used to refer to + this interface as source in various management protocol settings (future feature). + + On L2 switches, + this defaults to Vlan if either 'inband_mgmt_subnet' or 'inband_mgmt_ip' is set. + inband_mgmt_vlan: + VLAN number used for inband management on L2 switches (switches using port-channel trunks as + uplinks). + When using 'inband_mgmt_subnet' the VLAN and SVIs will be created automatically on this + switch as well as all 'uplink_switches'. + When using 'inband_mgmt_ip' the VLAN and SVI will only be + created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be + created using network services data models. + inband_mgmt_subnet: + Optional IP subnet assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ip virtual-router" and host-route injection based on + ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + + 3 + + GW on l2leafs : + 1 + Assign range larger than total l2leafs + 5 + Setting is ignored if 'inband_mgmt_ip' is set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + inband_mgmt_ip: + IP address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_subnet', hence all behavior of 'inband_mgmt_subnet' is removed. + + If this is set the + VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN and SVI on + the parent switches must be created using network services data models. + + This setting is applicable + to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_gateway: + Default gateway configured in the 'inband_mgmt_vrf' when using 'inband_mgmt_ip'. Otherwise gateway + is derived from 'inband_mgmt_subnet' if set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + inband_mgmt_ipv6_address: + IPv6 address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_ipv6_subnet', hence the configuration of 'inband_mgmt_ipv6_subnet' is ignored. + + If this + is set the VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN + and SVI on the parent switches must be created using network services data models. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_ipv6_subnet: + Optional IPv6 prefix assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ipv6 virtual-router" and host-route injection based + on ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN + extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + 3 + + GW on l2leafs : + 1 + Assign range larger than + total l2leafs + 5 + + Setting is ignored if 'inband_mgmt_ipv6_address' is set. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_ipv6_gateway: + Default gateway configured in the 'inband_mgmt_vrf'. + Used when `inband_mgmt_ipv6_address` is set. + Ignored when 'inband_mgmt_ipv6_subnet' is set (first IP in subnet used as gateway). + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_description: + Description configured on the Inband Management SVI. + + This setting is only applied on the devices + where it is set, it does not automatically affect any parent/child devices configuration, so it must + be set on each applicable node/node-group/node-type as needed. + inband_mgmt_vlan_name: + Name configured on the Inband Management VLAN. + This setting is only applied on the devices where it + is set, it does not automatically affect any parent/child devices configuration, so it must be set + on each applicable node/node-group/node-type as needed. + inband_mgmt_vrf: + VRF configured on the Inband Management Interface. + The VRF is created if not already created by + other means. + This setting is only applied on the devices where it is set, it does not automatically + affect any parent/child devices configuration, so it must be set on each applicable node/node- + group/node-type as needed. + inband_mgmt_mtu: + MTU configured on the Inband Management Interface. + This setting is only applied on the devices where + it is set, it does not automatically affect any parent/child devices configuration, so it must be + set on each applicable node/node-group/node-type as needed. + inband_ztp: + Enable to configure upstream device with proper configuration to allow downstream devices to be + Zero-Touch-Provisioned over the uplink interfaces. + For L2 devices this setting also requires that + the `inband_mgmt_vlan` is set for the node. + + PREVIEW: Support for L3 devices is marked as "preview", + meaning the data models or generated configuration can change at any time. + inband_ztp_lacp_fallback_delay: + Set the LACP fallback timeout of the upstream device's port-channel towards the downstream inband + ZTP node. + This setting also requires that `inband_ztp` is set for the node. + mpls_overlay_role: + Set the default mpls overlay role. + Acting role in overlay control plane. + overlay_address_families: + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + mpls_route_reflectors: + List of inventory hostname acting as MPLS route-reflectors. + + Subclass of AvdList with `str` items. + bgp_cluster_id: Set BGP cluster id. + ptp: Subclass of AvdModel. + wan_role: + Override the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + cv_pathfinder_transit_mode: + Configure the transit mode for a WAN client for CV Pathfinder designs + only when the `wan_mode` root + key is set to `cv_pathfinder`. + + 'zone' is currently not supported. + cv_pathfinder_region: + The CV Pathfinder region name. + This key is required for WAN routers but optional for pathfinders. + The region name must be defined under 'cv_pathfinder_regions'. + cv_pathfinder_site: + The CV Pathfinder site name. + This key is required for WAN routers but optional for pathfinders. + For + WAN routers and pathfinders with `cv_pathfinder_region`, the site name must be defined for the + relevant region under 'cv_pathfinder_regions'. + For pathfinders without `cv_pathfinder_region` set, + the site must be defined under `cv_pathfinder_global_sites`. + wan_ha: + PREVIEW: This key is currently not supported + + The key is supported only if `wan_mode` == `cv- + pathfinder`. + AutoVPN support is still to be determined. + + Maximum 2 devices supported by group for + HA. + + Subclass of AvdModel. + dps_mss_ipv4: IPv4 MSS value configured under "router path-selection" on WAN Devices. + l3_interfaces: + L3 Interfaces to configure on the node. + Used to define the node for WAN interfaces when + `wan_carrier` is set. + + Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is + `name` (`str`). + data_plane_cpu_allocation_max: + Set the maximum number of CPU used for the data plane. + This setting is useful on virtual Route + Reflectors and Pathfinders where more CPU cores should be allocated for control plane. + flow_tracker_type: + Set the flow tracker type. + Override the `default_flow_tracker_type`` set at the `node_type_key` + level. + `default_flow_tracker_type` default value is `sampled`. + _custom_data: _custom_data + + """ + + class NodeGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class NodesItem(AvdModel): + """Subclass of AvdModel.""" + + class DownlinkPoolsItem(AvdModel): + """Subclass of AvdModel.""" + + class DownlinkInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DownlinkInterfaces._item_type = str + + _fields: ClassVar[dict] = { + "ipv4_pool": {"type": str}, + "downlink_interfaces": {"type": DownlinkInterfaces}, + "_custom_data": {"type": dict}, + } + ipv4_pool: str | None + """IPv4 pool from which subnets will be allocated for links to downlink switches.""" + downlink_interfaces: DownlinkInterfaces + """ + List of downlink interfaces or ranges of interfaces to use this pool. The index of the interface in + this list will determine which subnet will be taken from the pool. + + Subclass of AvdList with `str` + items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4_pool: str | None | UndefinedType = Undefined, + downlink_interfaces: DownlinkInterfaces | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DownlinkPoolsItem. + + + Subclass of AvdModel. + + Args: + ipv4_pool: IPv4 pool from which subnets will be allocated for links to downlink switches. + downlink_interfaces: + List of downlink interfaces or ranges of interfaces to use this pool. The index of the interface in + this list will determine which subnet will be taken from the pool. + + Subclass of AvdList with `str` + items. + _custom_data: _custom_data + + """ + + class DownlinkPools(AvdList[DownlinkPoolsItem]): + """Subclass of AvdList with `DownlinkPoolsItem` items.""" + + DownlinkPools._item_type = DownlinkPoolsItem + + class LinkTracking(AvdModel): + """Subclass of AvdModel.""" + + class GroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "recovery_delay": {"type": int}, + "links_minimum": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str | None + """Tracking group name.""" + recovery_delay: int | None + """default -> platform_settings_mlag_reload_delay -> 300.""" + links_minimum: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + recovery_delay: int | None | UndefinedType = Undefined, + links_minimum: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GroupsItem. + + + Subclass of AvdModel. + + Args: + name: Tracking group name. + recovery_delay: default -> platform_settings_mlag_reload_delay -> 300. + links_minimum: links_minimum + _custom_data: _custom_data + + """ + + class Groups(AvdList[GroupsItem]): + """Subclass of AvdList with `GroupsItem` items.""" + + Groups._item_type = GroupsItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "groups": {"type": Groups, "default": lambda cls: coerce_type([{"name": "LT_GROUP1"}], target_type=cls)}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + groups: Groups + """ + Link Tracking Groups. + By default a single group named "LT_GROUP1" is defined with default values. + Any groups defined under "groups" will replace the default. + + + Subclass of AvdList with `GroupsItem` + items. + + Default value: `lambda cls: coerce_type([{"name": "LT_GROUP1"}], target_type=cls)` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + groups: + Link Tracking Groups. + By default a single group named "LT_GROUP1" is defined with default values. + Any groups defined under "groups" will replace the default. + + + Subclass of AvdList with `GroupsItem` + items. + _custom_data: _custom_data + + """ + + class LacpPortIdRange(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "size": {"type": int, "default": 128}, + "offset": {"type": int, "default": 0}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + size: int + """ + Recommended size > = number of ports in the switch. + + Default value: `128` + """ + offset: int + """ + Offset is used to avoid overlapping port-id ranges of different switches. + Useful when a "connected- + endpoint" is connected to switches in different "node_groups". + + Default value: `0` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + size: int | UndefinedType = Undefined, + offset: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LacpPortIdRange. + + + Subclass of AvdModel. + + Args: + enabled: enabled + size: Recommended size > = number of ports in the switch. + offset: + Offset is used to avoid overlapping port-id ranges of different switches. + Useful when a "connected- + endpoint" is connected to switches in different "node_groups". + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen): + """Subclass of AvdModel.""" + + class UplinkInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkInterfaces._item_type = str + + class UplinkSwitchInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkSwitchInterfaces._item_type = str + + class UplinkSwitches(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkSwitches._item_type = str + + class UplinkPtp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enable": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enable: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, enable: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + UplinkPtp. + + + Subclass of AvdModel. + + Args: + enable: enable + _custom_data: _custom_data + + """ + + class UplinkMacsec(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "_custom_data": {"type": dict}} + profile: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, profile: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + UplinkMacsec. + + + Subclass of AvdModel. + + Args: + profile: profile + _custom_data: _custom_data + + """ + + class MlagPortChannelStructuredConfig(EosCliConfigGen.PortChannelInterfacesItem): + """Subclass of AvdModel.""" + + class MlagPeerVlanStructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + class MlagPeerL3VlanStructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + class BgpDefaults(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + BgpDefaults._item_type = str + + class EvpnRouteServers(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + EvpnRouteServers._item_type = str + + class Filter(AvdModel): + """Subclass of AvdModel.""" + + class Tenants(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tenants._item_type = str + + class Tags(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tags._item_type = str + + class AllowVrfs(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AllowVrfs._item_type = str + + class DenyVrfs(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DenyVrfs._item_type = str + + class AlwaysIncludeVrfsInTenants(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AlwaysIncludeVrfsInTenants._item_type = str + + _fields: ClassVar[dict] = { + "tenants": {"type": Tenants, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "tags": {"type": Tags, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "allow_vrfs": {"type": AllowVrfs, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "deny_vrfs": {"type": DenyVrfs, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "always_include_vrfs_in_tenants": {"type": AlwaysIncludeVrfsInTenants}, + "only_vlans_in_use": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + tenants: Tenants + """ + Limit configured Network Services to those defined under these Tenants. Set to ['all'] for all + Tenants (default). + This list also limits Tenants included by `always_include_vrfs_in_tenants`. + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + tags: Tags + """ + Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default). + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + allow_vrfs: AllowVrfs + """ + Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs + (default). + This list also limits VRFs included by `always_include_vrfs_in_tenants`. + + Subclass of + AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + deny_vrfs: DenyVrfs + """ + Prevent configuration of Network Services defined under these VRFs. + This list prevents the given + VRFs to be included by any other filtering mechanism. + + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + always_include_vrfs_in_tenants: AlwaysIncludeVrfsInTenants + """ + List of tenants where VRFs will be configured even if VLANs are not included in tags. + Useful for L3 + "border" leaf. + + + Subclass of AvdList with `str` items. + """ + only_vlans_in_use: bool + """ + Only configure VLANs, SVIs, VRFs in use by connected endpoints or downstream L2 switches. + Note! This + feature only considers configuration managed by eos_designs. + This excludes structured_config, + custom_structured_configuration_, raw_eos_cli, eos_cli, custom templates, configlets etc. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + tenants: Tenants | UndefinedType = Undefined, + tags: Tags | UndefinedType = Undefined, + allow_vrfs: AllowVrfs | UndefinedType = Undefined, + deny_vrfs: DenyVrfs | UndefinedType = Undefined, + always_include_vrfs_in_tenants: AlwaysIncludeVrfsInTenants | UndefinedType = Undefined, + only_vlans_in_use: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Filter. + + + Subclass of AvdModel. + + Args: + tenants: + Limit configured Network Services to those defined under these Tenants. Set to ['all'] for all + Tenants (default). + This list also limits Tenants included by `always_include_vrfs_in_tenants`. + Subclass of AvdList with `str` items. + tags: + Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default). + Subclass of AvdList with `str` items. + allow_vrfs: + Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs + (default). + This list also limits VRFs included by `always_include_vrfs_in_tenants`. + + Subclass of + AvdList with `str` items. + deny_vrfs: + Prevent configuration of Network Services defined under these VRFs. + This list prevents the given + VRFs to be included by any other filtering mechanism. + + Subclass of AvdList with `str` items. + always_include_vrfs_in_tenants: + List of tenants where VRFs will be configured even if VLANs are not included in tags. + Useful for L3 + "border" leaf. + + + Subclass of AvdList with `str` items. + only_vlans_in_use: + Only configure VLANs, SVIs, VRFs in use by connected endpoints or downstream L2 switches. + Note! This + feature only considers configuration managed by eos_designs. + This excludes structured_config, + custom_structured_configuration_, raw_eos_cli, eos_cli, custom templates, configlets etc. + _custom_data: _custom_data + + """ + + class EvpnGateway(AvdModel): + """Subclass of AvdModel.""" + + class RemotePeersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hostname": {"type": str}, + "ip_address": {"type": str}, + "bgp_as": {"type": str}, + "_custom_data": {"type": dict}, + } + hostname: str + """Hostname of remote EVPN GW server.""" + ip_address: str | None + """Peering IP of remote Route Server.""" + bgp_as: str | None + """ + Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being + interpreted as a float number. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: str | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + bgp_as: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemotePeersItem. + + + Subclass of AvdModel. + + Args: + hostname: Hostname of remote EVPN GW server. + ip_address: Peering IP of remote Route Server. + bgp_as: + Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being + interpreted as a float number. + _custom_data: _custom_data + + """ + + class RemotePeers(AvdIndexedList[str, RemotePeersItem]): + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + + _primary_key: ClassVar[str] = "hostname" + + RemotePeers._item_type = RemotePeersItem + + class EvpnL2(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enabled: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, enabled: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + EvpnL2. + + + Subclass of AvdModel. + + Args: + enabled: enabled + _custom_data: _custom_data + + """ + + class EvpnL3(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "inter_domain": {"type": bool, "default": True}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + inter_domain: bool + """Default value: `True`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + inter_domain: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnL3. + + + Subclass of AvdModel. + + Args: + enabled: enabled + inter_domain: inter_domain + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "remote_peers": {"type": RemotePeers}, + "evpn_l2": {"type": EvpnL2}, + "evpn_l3": {"type": EvpnL3}, + "_custom_data": {"type": dict}, + } + remote_peers: RemotePeers + """ + Define remote peers of the EVPN VXLAN Gateway. + If the hostname can be found in the inventory, + ip_address and BGP ASN will be automatically populated. Manual override takes precedence. + If the + peer's hostname can not be found in the inventory, ip_address and bgp_as must be defined. + + + Subclass + of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + """ + evpn_l2: EvpnL2 + """ + Enable EVPN Gateway functionality for route-types 2 (MAC-IP) and 3 (IMET). + + Subclass of AvdModel. + """ + evpn_l3: EvpnL3 + """ + Enable EVPN Gateway functionality for route-type 5 (IP-PREFIX). + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + remote_peers: RemotePeers | UndefinedType = Undefined, + evpn_l2: EvpnL2 | UndefinedType = Undefined, + evpn_l3: EvpnL3 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnGateway. + + + Subclass of AvdModel. + + Args: + remote_peers: + Define remote peers of the EVPN VXLAN Gateway. + If the hostname can be found in the inventory, + ip_address and BGP ASN will be automatically populated. Manual override takes precedence. + If the + peer's hostname can not be found in the inventory, ip_address and bgp_as must be defined. + + + Subclass + of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + evpn_l2: + Enable EVPN Gateway functionality for route-types 2 (MAC-IP) and 3 (IMET). + + Subclass of AvdModel. + evpn_l3: + Enable EVPN Gateway functionality for route-type 5 (IP-PREFIX). + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class IpvpnGateway(AvdModel): + """Subclass of AvdModel.""" + + class AddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AddressFamilies._item_type = str + + class RemotePeersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hostname": {"type": str}, + "ip_address": {"type": str}, + "bgp_as": {"type": str}, + "_custom_data": {"type": dict}, + } + hostname: str + """Hostname of remote IPVPN Peer.""" + ip_address: str + """Peering IP of remote IPVPN Peer.""" + bgp_as: str + """ + Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For + asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted + as a float number. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: str | UndefinedType = Undefined, + ip_address: str | UndefinedType = Undefined, + bgp_as: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemotePeersItem. + + + Subclass of AvdModel. + + Args: + hostname: Hostname of remote IPVPN Peer. + ip_address: Peering IP of remote IPVPN Peer. + bgp_as: + Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For + asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted + as a float number. + _custom_data: _custom_data + + """ + + class RemotePeers(AvdIndexedList[str, RemotePeersItem]): + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + + _primary_key: ClassVar[str] = "hostname" + + RemotePeers._item_type = RemotePeersItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "evpn_domain_id": {"type": str, "default": "65535:1"}, + "ipvpn_domain_id": {"type": str, "default": "65535:2"}, + "enable_d_path": {"type": bool, "default": True}, + "maximum_routes": {"type": int, "default": 0}, + "local_as": {"type": str}, + "address_families": {"type": AddressFamilies, "default": lambda cls: coerce_type(["vpn-ipv4"], target_type=cls)}, + "remote_peers": {"type": RemotePeers}, + "_custom_data": {"type": dict}, + } + enabled: bool + evpn_domain_id: str + """ + Domain ID to assign to EVPN address family for use with D-path. Format :. + + Default value: `"65535:1"` + """ + ipvpn_domain_id: str + """ + Domain ID to assign to IPVPN address families for use with D-path. Format :. + + Default value: `"65535:2"` + """ + enable_d_path: bool + """ + Enable D-path for use with BGP bestpath selection algorithm. + + Default value: `True` + """ + maximum_routes: int + """ + Maximum routes to accept from IPVPN remote peers. + + Default value: `0` + """ + local_as: str | None + """ + Local BGP AS applied to peering with IPVPN remote peers. + BGP AS <1-4294967295> or AS number in asdot + notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number. + """ + address_families: AddressFamilies + """ + IPVPN address families to enable for remote peers. + + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["vpn-ipv4"], target_type=cls)` + """ + remote_peers: RemotePeers + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + evpn_domain_id: str | UndefinedType = Undefined, + ipvpn_domain_id: str | UndefinedType = Undefined, + enable_d_path: bool | UndefinedType = Undefined, + maximum_routes: int | UndefinedType = Undefined, + local_as: str | None | UndefinedType = Undefined, + address_families: AddressFamilies | UndefinedType = Undefined, + remote_peers: RemotePeers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpvpnGateway. + + + Subclass of AvdModel. + + Args: + enabled: enabled + evpn_domain_id: Domain ID to assign to EVPN address family for use with D-path. Format :. + ipvpn_domain_id: Domain ID to assign to IPVPN address families for use with D-path. Format :. + enable_d_path: Enable D-path for use with BGP bestpath selection algorithm. + maximum_routes: Maximum routes to accept from IPVPN remote peers. + local_as: + Local BGP AS applied to peering with IPVPN remote peers. + BGP AS <1-4294967295> or AS number in asdot + notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number. + address_families: + IPVPN address families to enable for remote peers. + + Subclass of AvdList with `str` items. + remote_peers: Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + _custom_data: _custom_data + + """ + + class MlagInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MlagInterfaces._item_type = str + + class OverlayAddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + OverlayAddressFamilies._item_type = str + + class MplsRouteReflectors(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MplsRouteReflectors._item_type = str + + class Ptp(AvdModel): + """Subclass of AvdModel.""" + + class Dscp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"general_messages": {"type": int}, "event_messages": {"type": int}, "_custom_data": {"type": dict}} + general_messages: int | None + event_messages: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + general_messages: int | None | UndefinedType = Undefined, + event_messages: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dscp. + + + Subclass of AvdModel. + + Args: + general_messages: general_messages + event_messages: event_messages + _custom_data: _custom_data + + """ + + class Monitor(AvdModel): + """Subclass of AvdModel.""" + + class Threshold(AvdModel): + """Subclass of AvdModel.""" + + class Drop(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "offset_from_master": {"type": int}, + "mean_path_delay": {"type": int}, + "_custom_data": {"type": dict}, + } + offset_from_master: int | None + mean_path_delay: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + offset_from_master: int | None | UndefinedType = Undefined, + mean_path_delay: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Drop. + + + Subclass of AvdModel. + + Args: + offset_from_master: offset_from_master + mean_path_delay: mean_path_delay + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "offset_from_master": {"type": int, "default": 250}, + "mean_path_delay": {"type": int, "default": 1500}, + "drop": {"type": Drop}, + "_custom_data": {"type": dict}, + } + offset_from_master: int + """Default value: `250`""" + mean_path_delay: int + """Default value: `1500`""" + drop: Drop + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + offset_from_master: int | UndefinedType = Undefined, + mean_path_delay: int | UndefinedType = Undefined, + drop: Drop | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Threshold. + + + Subclass of AvdModel. + + Args: + offset_from_master: offset_from_master + mean_path_delay: mean_path_delay + drop: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MissingMessage(AvdModel): + """Subclass of AvdModel.""" + + class Intervals(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "announce": {"type": int}, + "follow_up": {"type": int}, + "sync": {"type": int}, + "_custom_data": {"type": dict}, + } + announce: int | None + follow_up: int | None + sync: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + announce: int | None | UndefinedType = Undefined, + follow_up: int | None | UndefinedType = Undefined, + sync: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Intervals. + + + Subclass of AvdModel. + + Args: + announce: announce + follow_up: follow_up + sync: sync + _custom_data: _custom_data + + """ + + class SequenceIds(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "announce": {"type": int, "default": 3}, + "delay_resp": {"type": int, "default": 3}, + "follow_up": {"type": int, "default": 3}, + "sync": {"type": int, "default": 3}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + announce: int + """Default value: `3`""" + delay_resp: int + """Default value: `3`""" + follow_up: int + """Default value: `3`""" + sync: int + """Default value: `3`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + announce: int | UndefinedType = Undefined, + delay_resp: int | UndefinedType = Undefined, + follow_up: int | UndefinedType = Undefined, + sync: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceIds. + + + Subclass of AvdModel. + + Args: + enabled: enabled + announce: announce + delay_resp: delay_resp + follow_up: follow_up + sync: sync + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "intervals": {"type": Intervals}, + "sequence_ids": {"type": SequenceIds}, + "_custom_data": {"type": dict}, + } + intervals: Intervals + """Subclass of AvdModel.""" + sequence_ids: SequenceIds + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + intervals: Intervals | UndefinedType = Undefined, + sequence_ids: SequenceIds | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingMessage. + + + Subclass of AvdModel. + + Args: + intervals: Subclass of AvdModel. + sequence_ids: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "threshold": {"type": Threshold}, + "missing_message": {"type": MissingMessage}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + threshold: Threshold + """Subclass of AvdModel.""" + missing_message: MissingMessage + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + threshold: Threshold | UndefinedType = Undefined, + missing_message: MissingMessage | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Monitor. + + + Subclass of AvdModel. + + Args: + enabled: enabled + threshold: Subclass of AvdModel. + missing_message: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "profile": {"type": str}, + "mlag": {"type": bool, "default": False}, + "domain": {"type": int, "default": 127}, + "priority1": {"type": int}, + "priority2": {"type": int}, + "auto_clock_identity": {"type": bool}, + "clock_identity_prefix": {"type": str, "default": "00:1C:73"}, + "clock_identity": {"type": str}, + "source_ip": {"type": str}, + "mode": {"type": str, "default": "boundary"}, + "mode_one_step": {"type": bool, "default": False}, + "ttl": {"type": int}, + "forward_unicast": {"type": bool, "default": False}, + "dscp": {"type": Dscp}, + "monitor": {"type": Monitor}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + profile: str | None + """ + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + """ + mlag: bool + """ + Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be + configured on the MLAG peer-link port-channel. + + Default value: `False` + """ + domain: int + """Default value: `127`""" + priority1: int | None + """default -> automatically set based on node_type.""" + priority2: int | None + """default -> (node_id modulus 256).""" + auto_clock_identity: bool | None + """ + If you prefer to have PTP clock identity be the system MAC-address of the switch, which is the + default EOS behaviour, simply disable the automatic PTP clock identity. + default -> + (clock_identity_prefix = 00:1C:73 (default)) + (PTP priority 1 as HEX) + ":00:" + (PTP priority 2 as + HEX). + """ + clock_identity_prefix: str + """ + PTP clock idetentiy 3-byte prefix. i.e. "01:02:03". + By default the 3-byte prefix is "00:1C:73". + This + can be overridden if auto_clock_identity is set to true (which is the default). + + Default value: `"00:1C:73"` + """ + clock_identity: str | None + """Set PTP clock identity manually. 6-byte value i.e. "01:02:03:04:05:06".""" + source_ip: str | None + """ + By default in EOS, PTP packets are sourced with an IP address from the routed port or from the + relevant SVI, which is the recommended behaviour. + This can be set manually if required, for example, + to a value of "10.1.2.3". + """ + mode: Literal["boundary"] + """Default value: `"boundary"`""" + mode_one_step: bool + """Default value: `False`""" + ttl: int | None + forward_unicast: bool + """ + Enable PTP unicast forwarding. + + Default value: `False` + """ + dscp: Dscp + """Subclass of AvdModel.""" + monitor: Monitor + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + profile: str | None | UndefinedType = Undefined, + mlag: bool | UndefinedType = Undefined, + domain: int | UndefinedType = Undefined, + priority1: int | None | UndefinedType = Undefined, + priority2: int | None | UndefinedType = Undefined, + auto_clock_identity: bool | None | UndefinedType = Undefined, + clock_identity_prefix: str | UndefinedType = Undefined, + clock_identity: str | None | UndefinedType = Undefined, + source_ip: str | None | UndefinedType = Undefined, + mode: Literal["boundary"] | UndefinedType = Undefined, + mode_one_step: bool | UndefinedType = Undefined, + ttl: int | None | UndefinedType = Undefined, + forward_unicast: bool | UndefinedType = Undefined, + dscp: Dscp | UndefinedType = Undefined, + monitor: Monitor | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ptp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + profile: + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + mlag: + Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be + configured on the MLAG peer-link port-channel. + domain: domain + priority1: default -> automatically set based on node_type. + priority2: default -> (node_id modulus 256). + auto_clock_identity: + If you prefer to have PTP clock identity be the system MAC-address of the switch, which is the + default EOS behaviour, simply disable the automatic PTP clock identity. + default -> + (clock_identity_prefix = 00:1C:73 (default)) + (PTP priority 1 as HEX) + ":00:" + (PTP priority 2 as + HEX). + clock_identity_prefix: + PTP clock idetentiy 3-byte prefix. i.e. "01:02:03". + By default the 3-byte prefix is "00:1C:73". + This + can be overridden if auto_clock_identity is set to true (which is the default). + clock_identity: Set PTP clock identity manually. 6-byte value i.e. "01:02:03:04:05:06". + source_ip: + By default in EOS, PTP packets are sourced with an IP address from the routed port or from the + relevant SVI, which is the recommended behaviour. + This can be set manually if required, for example, + to a value of "10.1.2.3". + mode: mode + mode_one_step: mode_one_step + ttl: ttl + forward_unicast: Enable PTP unicast forwarding. + dscp: Subclass of AvdModel. + monitor: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class WanHa(AvdModel): + """Subclass of AvdModel.""" + + class HaInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + HaInterfaces._item_type = str + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "ipsec": {"type": bool, "default": True}, + "mtu": {"type": int, "default": 9194}, + "ha_interfaces": {"type": HaInterfaces}, + "ha_ipv4_pool": {"type": str}, + "max_ha_interfaces": {"type": int}, + "port_channel_id": {"type": int}, + "use_port_channel_for_direct_ha": {"type": bool, "default": True}, + "flow_tracking": {"type": FlowTracking}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group.""" + ipsec: bool + """ + Enable / Disable IPsec over HA path-group when HA is enabled. + + Default value: `True` + """ + mtu: int + """ + Set MTU on WAN HA interfaces. + + Default value: `9194` + """ + ha_interfaces: HaInterfaces + """ + Local WAN HA interfaces + Overwrite the default behavior which is to pick all the `uplink_interfaces`. + Can be used to filter uplink interfaces when there are multiple uplinks. + Limitations: + Either all + interfaces must be uplinks or all interfaces must not be uplinks. + Only one interface is supported + for non uplinks. + + Subclass of AvdList with `str` items. + """ + ha_ipv4_pool: str | None + """ + IP address pool used for WAN HA connectivity. + IP is derived from the node ID. + Not used for uplink + interfaces. + """ + max_ha_interfaces: int | None + """ + Number of parallel links towards HA switches. + Can be used to reserve IP addresses for future + parallel HA links. + """ + port_channel_id: int | None + """Port-channel ID to use for direct HA.""" + use_port_channel_for_direct_ha: bool + """ + Enable or disable using a port-channel interface for direct HA when there is only one interface. + This feature was introduced in EOS 4.33.0F. + + Default value: `True` + """ + flow_tracking: FlowTracking + """ + Configures flow-tracking on the HA interfaces. Overrides `fabric_flow_tracking.wan_ha_links` + setting. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + ipsec: bool | UndefinedType = Undefined, + mtu: int | UndefinedType = Undefined, + ha_interfaces: HaInterfaces | UndefinedType = Undefined, + ha_ipv4_pool: str | None | UndefinedType = Undefined, + max_ha_interfaces: int | None | UndefinedType = Undefined, + port_channel_id: int | None | UndefinedType = Undefined, + use_port_channel_for_direct_ha: bool | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + WanHa. + + + Subclass of AvdModel. + + Args: + enabled: Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group. + ipsec: Enable / Disable IPsec over HA path-group when HA is enabled. + mtu: Set MTU on WAN HA interfaces. + ha_interfaces: + Local WAN HA interfaces + Overwrite the default behavior which is to pick all the `uplink_interfaces`. + Can be used to filter uplink interfaces when there are multiple uplinks. + Limitations: + Either all + interfaces must be uplinks or all interfaces must not be uplinks. + Only one interface is supported + for non uplinks. + + Subclass of AvdList with `str` items. + ha_ipv4_pool: + IP address pool used for WAN HA connectivity. + IP is derived from the node ID. + Not used for uplink + interfaces. + max_ha_interfaces: + Number of parallel links towards HA switches. + Can be used to reserve IP addresses for future + parallel HA links. + port_channel_id: Port-channel ID to use for direct HA. + use_port_channel_for_direct_ha: + Enable or disable using a port-channel interface for direct HA when there is only one interface. + This feature was introduced in EOS 4.33.0F. + flow_tracking: + Configures flow-tracking on the HA interfaces. Overrides `fabric_flow_tracking.wan_ha_links` + setting. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L3InterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "peer_as": {"type": str}, + "ipv4_prefix_list_in": {"type": str}, + "ipv4_prefix_list_out": {"type": str}, + "_custom_data": {"type": dict}, + } + peer_as: str + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + ipv4_prefix_list_in: str | None + """ + Prefix List Name. Accept routes for only these prefixes from the peer. + Required for wan interfaces. + """ + ipv4_prefix_list_out: str | None + """ + Prefix List Name. Advertise routes for only these prefixes. + If not specified, nothing would be + advertised. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + peer_as: str | UndefinedType = Undefined, + ipv4_prefix_list_in: str | None | UndefinedType = Undefined, + ipv4_prefix_list_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + peer_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + ipv4_prefix_list_in: + Prefix List Name. Accept routes for only these prefixes from the peer. + Required for wan interfaces. + ipv4_prefix_list_out: + Prefix List Name. Advertise routes for only these prefixes. + If not specified, nothing would be + advertised. + _custom_data: _custom_data + + """ + + class StaticRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "_custom_data": {"type": dict}} + prefix: str + """IPv4_network/Mask.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, prefix: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + StaticRoutesItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv4_network/Mask. + _custom_data: _custom_data + + """ + + class StaticRoutes(AvdList[StaticRoutesItem]): + """Subclass of AvdList with `StaticRoutesItem` items.""" + + StaticRoutes._item_type = StaticRoutesItem + + class CvPathfinderInternetExit(AvdModel): + """Subclass of AvdModel.""" + + class PoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "tunnel_interface_numbers": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Internet-exit policy name.""" + tunnel_interface_numbers: str | None + """ + Number range to use for Tunnel interfaces to an internet-exit service provider using this local + interface. + Examples: '1-3' or '100,200,300' + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + tunnel_interface_numbers: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PoliciesItem. + + + Subclass of AvdModel. + + Args: + name: Internet-exit policy name. + tunnel_interface_numbers: + Number range to use for Tunnel interfaces to an internet-exit service provider using this local + interface. + Examples: '1-3' or '100,200,300' + _custom_data: _custom_data + + """ + + class Policies(AvdIndexedList[str, PoliciesItem]): + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Policies._item_type = PoliciesItem + + _fields: ClassVar[dict] = {"policies": {"type": Policies}, "_custom_data": {"type": dict}} + policies: Policies + """ + List of Internet-exit policies using this interface as exit. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, policies: Policies | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + CvPathfinderInternetExit. + + + Subclass of AvdModel. + + Args: + policies: + List of Internet-exit policies using this interface as exit. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "profile": {"type": str}, + "name": {"type": str}, + "description": {"type": str}, + "ip_address": {"type": str}, + "dhcp_ip": {"type": str}, + "public_ip": {"type": str}, + "encapsulation_dot1q_vlan": {"type": int}, + "dhcp_accept_default_route": {"type": bool, "default": True}, + "enabled": {"type": bool, "default": True}, + "speed": {"type": str}, + "peer": {"type": str}, + "peer_interface": {"type": str}, + "peer_ip": {"type": str}, + "bgp": {"type": Bgp}, + "ipv4_acl_in": {"type": str}, + "ipv4_acl_out": {"type": str}, + "static_routes": {"type": StaticRoutes}, + "qos_profile": {"type": str}, + "wan_carrier": {"type": str}, + "wan_circuit_id": {"type": str}, + "connected_to_pathfinder": {"type": bool, "default": True}, + "cv_pathfinder_internet_exit": {"type": CvPathfinderInternetExit}, + "raw_eos_cli": {"type": str}, + "flow_tracking": {"type": FlowTracking}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + profile: str | None + """L3 interface profile name. Profile defined under `l3_interface_profiles`.""" + name: str + """ + Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. + For a + subinterface, the parent physical interface is automatically created. + """ + description: str | None + """ + Interface description. + If not set a default description will be configured with '[[ + ]]'. + """ + ip_address: str | None + """Node IPv4 address/Mask or 'dhcp'.""" + dhcp_ip: str | None + """ + When the `ip_address` is `dhcp`, this optional field allows to indicate the expected + IPv4 address + (without mask) to be allocated on the interface if known. + This is not rendered in the configuration + but can be used for substitution of 'interface_ip' in the Access-list + set under `ipv4_acl_in` and + `ipv4_acl_out`. + """ + public_ip: str | None + """ + Node IPv4 address (no mask). + + This is used to get the public IP (if known) when the device is behind + NAT. + This is only used for `wan_rr` routers (AutoVPN RRs and Pathfinders) to determine the Public IP + with the following preference: + `wan_route_servers.path_groups.interfaces.ip_address` + -> + `l3_interfaces.public_ip` + -> `l3_interfaces.ip_address` + + The determined Public IP is used + by WAN routers when peering with this interface. + """ + encapsulation_dot1q_vlan: int | None + """ + For subinterfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + """ + dhcp_accept_default_route: bool + """ + Accept a default route from DHCP if `ip_address` is set to `dhcp`. + + Default value: `True` + """ + enabled: bool + """ + Enable or Shutdown the interface. + + Default value: `True` + """ + speed: str | None + """ + Speed should be set in the format `` or `forced ` or `auto + `. + """ + peer: str | None + """The peer device name. Used for description and documentation.""" + peer_interface: str | None + """The peer device interface. Used for description and documentation.""" + peer_ip: str | None + """ + The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true + and `ip` is an IP address. + """ + bgp: Bgp + """ + Enforce IPv4 BGP peering for the peer + + Subclass of AvdModel. + """ + ipv4_acl_in: str | None + """ + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + Required + for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under + `wan_carriers`. + """ + ipv4_acl_out: str | None + """ + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + """ + static_routes: StaticRoutes + """ + Configure IPv4 static routes pointing to `peer_ip`. + + Subclass of AvdList with `StaticRoutesItem` + items. + """ + qos_profile: str | None + """QOS service profile.""" + wan_carrier: str | None + """ + The WAN carrier this interface is connected to. + This is used to infer the path-groups in which this + interface should be configured. + Unless the carrier is marked as 'trusted' under `wan_carriers`, + `ipv4_acl_in` is also required on all WAN interfaces. + """ + wan_circuit_id: str | None + """ + The WAN circuit ID for this interface. + This is not rendered in the configuration but used for WAN + designs. + """ + connected_to_pathfinder: bool + """ + For a WAN interface (`wan_carrier` is set), allow to disable the static tunnel towards Pathfinders. + + Default value: `True` + """ + cv_pathfinder_internet_exit: CvPathfinderInternetExit + """ + PREVIEW: This key is in preview mode + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the interface in the final EOS configuration.""" + flow_tracking: FlowTracking + """ + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + """ + structured_config: StructuredConfig + """ + Custom structured config for the Ethernet interface. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | None | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + dhcp_ip: str | None | UndefinedType = Undefined, + public_ip: str | None | UndefinedType = Undefined, + encapsulation_dot1q_vlan: int | None | UndefinedType = Undefined, + dhcp_accept_default_route: bool | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + speed: str | None | UndefinedType = Undefined, + peer: str | None | UndefinedType = Undefined, + peer_interface: str | None | UndefinedType = Undefined, + peer_ip: str | None | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + ipv4_acl_in: str | None | UndefinedType = Undefined, + ipv4_acl_out: str | None | UndefinedType = Undefined, + static_routes: StaticRoutes | UndefinedType = Undefined, + qos_profile: str | None | UndefinedType = Undefined, + wan_carrier: str | None | UndefinedType = Undefined, + wan_circuit_id: str | None | UndefinedType = Undefined, + connected_to_pathfinder: bool | UndefinedType = Undefined, + cv_pathfinder_internet_exit: CvPathfinderInternetExit | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L3InterfacesItem. + + + Subclass of AvdModel. + + Args: + profile: L3 interface profile name. Profile defined under `l3_interface_profiles`. + name: + Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. + For a + subinterface, the parent physical interface is automatically created. + description: + Interface description. + If not set a default description will be configured with '[[ + ]]'. + ip_address: Node IPv4 address/Mask or 'dhcp'. + dhcp_ip: + When the `ip_address` is `dhcp`, this optional field allows to indicate the expected + IPv4 address + (without mask) to be allocated on the interface if known. + This is not rendered in the configuration + but can be used for substitution of 'interface_ip' in the Access-list + set under `ipv4_acl_in` and + `ipv4_acl_out`. + public_ip: + Node IPv4 address (no mask). + + This is used to get the public IP (if known) when the device is behind + NAT. + This is only used for `wan_rr` routers (AutoVPN RRs and Pathfinders) to determine the Public IP + with the following preference: + `wan_route_servers.path_groups.interfaces.ip_address` + -> + `l3_interfaces.public_ip` + -> `l3_interfaces.ip_address` + + The determined Public IP is used + by WAN routers when peering with this interface. + encapsulation_dot1q_vlan: + For subinterfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + dhcp_accept_default_route: Accept a default route from DHCP if `ip_address` is set to `dhcp`. + enabled: Enable or Shutdown the interface. + speed: + Speed should be set in the format `` or `forced ` or `auto + `. + peer: The peer device name. Used for description and documentation. + peer_interface: The peer device interface. Used for description and documentation. + peer_ip: + The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true + and `ip` is an IP address. + bgp: + Enforce IPv4 BGP peering for the peer + + Subclass of AvdModel. + ipv4_acl_in: + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + Required + for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under + `wan_carriers`. + ipv4_acl_out: + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + static_routes: + Configure IPv4 static routes pointing to `peer_ip`. + + Subclass of AvdList with `StaticRoutesItem` + items. + qos_profile: QOS service profile. + wan_carrier: + The WAN carrier this interface is connected to. + This is used to infer the path-groups in which this + interface should be configured. + Unless the carrier is marked as 'trusted' under `wan_carriers`, + `ipv4_acl_in` is also required on all WAN interfaces. + wan_circuit_id: + The WAN circuit ID for this interface. + This is not rendered in the configuration but used for WAN + designs. + connected_to_pathfinder: For a WAN interface (`wan_carrier` is set), allow to disable the static tunnel towards Pathfinders. + cv_pathfinder_internet_exit: + PREVIEW: This key is in preview mode + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the interface in the final EOS configuration. + flow_tracking: + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + structured_config: + Custom structured config for the Ethernet interface. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): + """Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + L3Interfaces._item_type = L3InterfacesItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "downlink_pools": {"type": DownlinkPools}, + "id": {"type": int}, + "platform": {"type": str}, + "mac_address": {"type": str}, + "system_mac_address": {"type": str}, + "serial_number": {"type": str}, + "rack": {"type": str}, + "mgmt_ip": {"type": str}, + "mgmt_gateway": {"type": str}, + "ipv6_mgmt_ip": {"type": str}, + "ipv6_mgmt_gateway": {"type": str}, + "mgmt_interface": {"type": str}, + "link_tracking": {"type": LinkTracking}, + "lacp_port_id_range": {"type": LacpPortIdRange}, + "always_configure_ip_routing": {"type": bool, "default": False}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "uplink_type": {"type": str}, + "uplink_ipv4_pool": {"type": str}, + "uplink_interfaces": {"type": UplinkInterfaces}, + "uplink_switch_interfaces": {"type": UplinkSwitchInterfaces}, + "uplink_switches": {"type": UplinkSwitches}, + "uplink_interface_speed": {"type": str}, + "uplink_switch_interface_speed": {"type": str}, + "uplink_mtu": {"type": int}, + "max_uplink_switches": {"type": int}, + "max_parallel_uplinks": {"type": int, "default": 1}, + "uplink_bfd": {"type": bool, "default": False}, + "uplink_native_vlan": {"type": int}, + "uplink_ptp": {"type": UplinkPtp}, + "uplink_macsec": {"type": UplinkMacsec}, + "uplink_port_channel_id": {"type": int}, + "uplink_switch_port_channel_id": {"type": int}, + "uplink_structured_config": {"type": dict}, + "mlag_port_channel_structured_config": {"type": MlagPortChannelStructuredConfig}, + "mlag_peer_vlan_structured_config": {"type": MlagPeerVlanStructuredConfig}, + "mlag_peer_l3_vlan_structured_config": {"type": MlagPeerL3VlanStructuredConfig}, + "short_esi": {"type": str}, + "isis_system_id_prefix": {"type": str}, + "isis_maximum_paths": {"type": int}, + "is_type": {"type": str}, + "node_sid_base": {"type": int, "default": 0}, + "loopback_ipv4_pool": {"type": str}, + "loopback_ipv4_address": {"type": str}, + "vtep_loopback_ipv4_pool": {"type": str}, + "vtep_loopback_ipv4_address": {"type": str}, + "loopback_ipv4_offset": {"type": int, "default": 0}, + "loopback_ipv6_pool": {"type": str}, + "loopback_ipv6_offset": {"type": int, "default": 0}, + "vtep": {"type": bool}, + "vtep_loopback": {"type": str}, + "bgp_as": {"type": str}, + "bgp_defaults": {"type": BgpDefaults}, + "evpn_role": {"type": str}, + "evpn_route_servers": {"type": EvpnRouteServers}, + "evpn_services_l2_only": {"type": bool, "default": False}, + "filter": {"type": Filter}, + "igmp_snooping_enabled": {"type": bool}, + "evpn_gateway": {"type": EvpnGateway}, + "ipvpn_gateway": {"type": IpvpnGateway}, + "mlag": {"type": bool, "default": True}, + "mlag_dual_primary_detection": {"type": bool, "default": False}, + "mlag_ibgp_origin_incomplete": {"type": bool, "default": True}, + "mlag_interfaces": {"type": MlagInterfaces}, + "mlag_interfaces_speed": {"type": str}, + "mlag_peer_l3_vlan": {"type": int, "default": 4093}, + "mlag_peer_l3_ipv4_pool": {"type": str}, + "mlag_peer_vlan": {"type": int, "default": 4094}, + "mlag_peer_link_allowed_vlans": {"type": str}, + "mlag_peer_address_family": {"type": str, "default": "ipv4"}, + "mlag_peer_ipv4_pool": {"type": str}, + "mlag_peer_ipv6_pool": {"type": str}, + "mlag_port_channel_id": {"type": int}, + "mlag_domain_id": {"type": str}, + "spanning_tree_mode": {"type": str}, + "spanning_tree_priority": {"type": int, "default": 32768}, + "spanning_tree_root_super": {"type": bool, "default": False}, + "virtual_router_mac_address": {"type": str}, + "inband_mgmt_interface": {"type": str}, + "inband_mgmt_vlan": {"type": int, "default": 4092}, + "inband_mgmt_subnet": {"type": str}, + "inband_mgmt_ip": {"type": str}, + "inband_mgmt_gateway": {"type": str}, + "inband_mgmt_ipv6_address": {"type": str}, + "inband_mgmt_ipv6_subnet": {"type": str}, + "inband_mgmt_ipv6_gateway": {"type": str}, + "inband_mgmt_description": {"type": str, "default": "Inband Management"}, + "inband_mgmt_vlan_name": {"type": str, "default": "INBAND_MGMT"}, + "inband_mgmt_vrf": {"type": str, "default": "default"}, + "inband_mgmt_mtu": {"type": int, "default": 1500}, + "inband_ztp": {"type": bool, "default": False}, + "inband_ztp_lacp_fallback_delay": {"type": int, "default": 30}, + "mpls_overlay_role": {"type": str}, + "overlay_address_families": {"type": OverlayAddressFamilies}, + "mpls_route_reflectors": {"type": MplsRouteReflectors}, + "bgp_cluster_id": {"type": str}, + "ptp": {"type": Ptp}, + "wan_role": {"type": str}, + "cv_pathfinder_transit_mode": {"type": str}, + "cv_pathfinder_region": {"type": str}, + "cv_pathfinder_site": {"type": str}, + "wan_ha": {"type": WanHa}, + "dps_mss_ipv4": {"type": str, "default": "auto"}, + "l3_interfaces": {"type": L3Interfaces}, + "data_plane_cpu_allocation_max": {"type": int}, + "flow_tracker_type": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """The Node Name is used as "hostname".""" + downlink_pools: DownlinkPools + """ + IPv4 pools used for links to downlink switches. Set this on the parent switch. Cannot be combined + with `uplink_ipv4_pool` set on the downlink switch. + + Subclass of AvdList with `DownlinkPoolsItem` + items. + """ + id: int | None + """Unique identifier used for IP addressing and other algorithms.""" + platform: str | None + """Arista platform family.""" + mac_address: str | None + """Leverage to document management interface mac address.""" + system_mac_address: str | None + """ + System MAC Address in this following format: "xx:xx:xx:xx:xx:xx". + Set to the same MAC address as + available in "show version" on the device. + "system_mac_address" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + """ + serial_number: str | None + """ + Set to the Serial Number of the device. + Only used for documentation purpose in the fabric + documentation and part of the structured_config. + "serial_number" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + """ + rack: str | None + """Rack that the switch is located in (only used in snmp_settings location).""" + mgmt_ip: str | None + """Node management interface IPv4 address.""" + mgmt_gateway: str | None + """ + This key sets the management gateway for the device. It takes precedence over the global + `mgmt_gateway`. + """ + ipv6_mgmt_ip: str | None + """Node management interface IPv6 address.""" + ipv6_mgmt_gateway: str | None + """ + This key sets the ipv6 management gateway for the device. It takes precedence over the global + `ipv6_mgmt_gateway`. + """ + mgmt_interface: str | None + """ + Management Interface Name. + Default -> platform_management_interface -> mgmt_interface -> + "Management1". + """ + link_tracking: LinkTracking + """ + This configures the Link Tracking Group on a switch as well as adds the p2p-uplinks of the switch as + the upstream interfaces. + Useful in EVPN multhoming designs. + + + Subclass of AvdModel. + """ + lacp_port_id_range: LacpPortIdRange + """ + This will generate the "lacp port-id range", "begin" and "end" values based on node "id" and the + number of nodes in the "node_group". + Unique LACP port-id ranges are recommended for EVPN Multihoming + designs. + + + Subclass of AvdModel. + """ + always_configure_ip_routing: bool + """ + Force configuration of "ip routing" even on L2 devices. + Use this to retain behavior of AVD versions + below 4.0.0. + + Default value: `False` + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the root level of the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + """ + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None + """ + Override the default `uplink_type` set at the `node_type_key` level. + `uplink_type` must be "p2p" if + `vtep` or `underlay_router` is true for the `node_type_key` definition. + """ + uplink_ipv4_pool: str | None + """IPv4 subnet to use to connect to uplink switches.""" + uplink_interfaces: UplinkInterfaces + """ + Local uplink interfaces. + Each list item supports range syntax that can be expanded into a list of + interfaces. + If uplink_interfaces is not defined, platform-specific defaults (defined under + default_interfaces) will be used instead. + Please note that default_interfaces are not defined by + default, you should define these yourself. + + + Subclass of AvdList with `str` items. + """ + uplink_switch_interfaces: UplinkSwitchInterfaces + """ + Interfaces located on uplink switches. + + Subclass of AvdList with `str` items. + """ + uplink_switches: UplinkSwitches + """Subclass of AvdList with `str` items.""" + uplink_interface_speed: str | None + """ + Set point-to-Point interface speed and will apply to uplink interfaces on both ends. + (Uplink switch + interface speed can be overridden with `uplink_switch_interface_speed`). + Speed should be set in the + format `` or `forced ` or `auto `. + """ + uplink_switch_interface_speed: str | None + """ + 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: int | None + """Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting.""" + max_uplink_switches: int | None + """ + 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: 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 + """ + Enable bfd on uplink interfaces. + + Default value: `False` + """ + uplink_native_vlan: int | None + """ + 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: UplinkPtp + """ + Enable PTP on all infrastructure links. + + Subclass of AvdModel. + """ + uplink_macsec: UplinkMacsec + """ + Enable MacSec on all uplinks. + + Subclass of AvdModel. + """ + uplink_port_channel_id: int | None + """ + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink Port-channel + ID will be set to the number of the lowest member interface defined under `uplink_interfaces`. + For + example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ Eth11/1, Eth22/1 ] -> ID 111 + For + MLAG port-channels ID will be based on the lowest member interface on the first MLAG switch. + This + option overrides the default behavior and statically sets the local Port-channel ID. + Note! Make sure + the ID is unique and does not overlap with autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between 1 and 2000 and both MLAG switches must have the same + value. + """ + uplink_switch_port_channel_id: int | None + """ + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink switch Port- + channel ID will be set to the number of the first interface defined under + `uplink_switch_interfaces`. + For example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ + Eth11/1, Eth22/1 ] -> ID 111 + For MLAG port-channels ID will be based on the lowest member interface + on the first MLAG switch. + This option overrides the default behavior and statically sets the Port- + channel ID on the uplink switch. + Note! Make sure the ID is unique and does not overlap with + autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between + 1 and 2000 and both MLAG switches must have the same value. + """ + uplink_structured_config: dict + """ + Custom structured config applied to "uplink_interfaces", and "uplink_switch_interfaces". + When + uplink_type == "p2p", custom structured config added under ethernet_interfaces.[name=] + for eos_cli_config_gen overrides the settings on the ethernet interface level. + When uplink_type == + "port-channel", custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen overrides the settings on the port-channel interface level. + "uplink_structured_config" is applied after "structured_config", so it can override + "structured_config" defined on node-level. + Note! The content of this dictionary is _not_ validated + by the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + """ + mlag_port_channel_structured_config: MlagPortChannelStructuredConfig + """ + Custom structured config applied to MLAG peer link port-channel id. + Added under + port_channel_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the + port-channel interface level. + "mlag_port_channel_structured_config" is applied after + "structured_config", so it can override "structured_config" defined on node-level. + + + Subclass of + AvdModel. + """ + mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig + """ + Custom structured config applied to MLAG Peer Link (control link) SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_vlan_structured_config" is applied after "structured_config", so it can + override "structured_config" defined on node-level. + + + Subclass of AvdModel. + """ + mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig + """ + Custom structured config applied to MLAG underlay L3 peering SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_l3_vlan_structured_config" is applied after "structured_config", so it + can override "structured_config" defined on node-level. + + + Subclass of AvdModel. + """ + short_esi: str | None + """ + short_esi only valid for l2leaf devices using port-channel uplink. + Setting short_esi to "auto" + generates the short_esi automatically using a hash of configuration elements. + < 0000:0000:0000 | + auto >. + """ + isis_system_id_prefix: str | None + """(4.4 hexadecimal).""" + isis_maximum_paths: int | None + """Number of path to configure in ECMP for ISIS.""" + is_type: Literal["level-1-2", "level-1", "level-2"] | None + """Overrides `isis_default_is_type`.""" + node_sid_base: int + """ + Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID. + + Default value: `0` + """ + loopback_ipv4_pool: str | None + """IPv4 subnet for Loopback0 allocation.""" + loopback_ipv4_address: str | None + """ + IPv4 address without mask for Loopback0. + When set, it takes precedence over `loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not catch duplicates. + """ + vtep_loopback_ipv4_pool: str | None + """IPv4 subnet for VTEP-Loopback allocation.""" + vtep_loopback_ipv4_address: str | None + """ + IPv4 address without mask for VTEP-Loopback. + When set, it takes precedence over + `vtep_loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not + catch duplicates. + """ + loopback_ipv4_offset: int + """ + Offset all assigned loopback IP addresses. + Required when the < loopback_ipv4_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid over-lapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv4_offset: < total # spine switches > or vice versa. + + Default value: `0` + """ + loopback_ipv6_pool: str | None + """IPv6 subnet for Loopback0 allocation.""" + loopback_ipv6_offset: int + """ + Offset all assigned loopback IPv6 addresses. + Required when the < loopback_ipv6_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid overlapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv6_offset: < total # spine switches > or vice versa. + + Default value: `0` + """ + vtep: bool | None + """ + Node is configured as a VTEP when applicable based on 'overlay_routing_protocol'. + Overrides VTEP + setting inherited from node_type_keys. + """ + vtep_loopback: str | None + """Set VXLAN source interface.""" + bgp_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + Required with eBGP. + """ + bgp_defaults: BgpDefaults + """ + List of EOS commands to apply to BGP daemon. + + Subclass of AvdList with `str` items. + """ + evpn_role: Literal["client", "server", "none"] | None + """ + Acting role in EVPN control plane. + Default is set in node_type definition from node_type_keys. + """ + evpn_route_servers: EvpnRouteServers + """ + List of nodes acting as EVPN Route-Servers / Route-Reflectors. + + Subclass of AvdList with `str` + items. + """ + evpn_services_l2_only: bool + """ + Possibility to prevent configuration of Tenant VRFs and SVIs. + Override node definition + "network_services_l3" from node_type_keys. + This allows support for centralized routing. + + Default value: `False` + """ + filter: Filter + """ + Filter L3 and L2 network services based on tenant and tags (and operation filter). + If filter is not + defined it will default to all. + + + Subclass of AvdModel. + """ + igmp_snooping_enabled: bool | None + """Activate or deactivate IGMP snooping on device level.""" + evpn_gateway: EvpnGateway + """ + Node is acting as EVPN Multi-Domain Gateway. + New BGP peer-group is generated between EVPN GWs in + different domains or between GWs and Route Servers. + Name can be changed under + "bgp_peer_groups.evpn_overlay_core" variable. + L3 rechability for different EVPN GWs must be already + in place, it is recommended to use DCI & L3 Edge if Route Servers and GWs are not defined under the + same Ansible inventory. + + + Subclass of AvdModel. + """ + ipvpn_gateway: IpvpnGateway + """ + Node is acting as IP-VPN Gateway for EVPN to MPLS-IP-VPN Interworking. The BGP peer group used for + this is "bgp_peer_groups.ipvpn_gateway_peers". + L3 Reachability is required for this to work, the + preferred method to establish underlay connectivity is to use core_interfaces. + + + Subclass of + AvdModel. + """ + mlag: bool + """ + Enable / Disable auto MLAG, when two nodes are defined in node group. + + Default value: `True` + """ + mlag_dual_primary_detection: bool + """ + Enable / Disable MLAG dual primary detection. + + Default value: `False` + """ + mlag_ibgp_origin_incomplete: bool + """ + Set origin of routes received from MLAG iBGP peer to incomplete. + The purpose is to optimize routing + for leaf loopbacks from spine perspective and + avoid suboptimal routing via peerlink for control + plane traffic. + + Default value: `True` + """ + mlag_interfaces: MlagInterfaces + """ + Each list item supports range syntax that can be expanded into a list of interfaces. + Required when + MLAG leafs are present in the topology. + + + Subclass of AvdList with `str` items. + """ + mlag_interfaces_speed: str | None + """ + Set MLAG interface speed. + Speed should be set in the format `` or `forced + ` or `auto `. + """ + mlag_peer_l3_vlan: int + """ + Underlay L3 peering SVI interface id. + If set to 0 or the same vlan as mlag_peer_vlan, the + mlag_peer_vlan will be used for L3 peering. + + Default value: `4093` + """ + mlag_peer_l3_ipv4_pool: str | None + """ + IP address pool used for MLAG underlay L3 peering. IP is derived from the node id. + Required when + MLAG leafs present in topology and they are using a separate L3 peering VLAN. + """ + mlag_peer_vlan: int + """ + MLAG Peer Link (control link) SVI interface id. + + Default value: `4094` + """ + mlag_peer_link_allowed_vlans: str | None + mlag_peer_address_family: Literal["ipv4", "ipv6"] + """ + IP address family used to establish MLAG Peer Link (control link). + `ipv6` requires EOS version + 4.31.1F or higher. + Note: `ipv6` is not supported in combination with a common MLAG peer link VLAN + (ex. `mlag_peer_l3_vlan` set to 4094). + + Default value: `"ipv4"` + """ + mlag_peer_ipv4_pool: str | None + """ + IPv4 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv4` (default). + """ + mlag_peer_ipv6_pool: str | None + """ + IPv6 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv6`. + """ + mlag_port_channel_id: int | None + """ + If not set, the mlag port-channel id is generated based on the digits of the first interface present + in 'mlag_interfaces'. + Valid port-channel id numbers are < 1-2000 > for EOS < 4.25.0F and < 1 - + 999999 > for EOS >= 4.25.0F. + """ + mlag_domain_id: str | None + """MLAG Domain ID. If not set the node group name (Set with "group" key) will be used.""" + spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None + spanning_tree_priority: int + """ + Spanning-tree priority configured for the selected mode. + For `rapid-pvst` the priority can also be + set per VLAN under network services. + + Default value: `32768` + """ + spanning_tree_root_super: bool + """Default value: `False`""" + virtual_router_mac_address: str | None + """Virtual router mac address for anycast gateway.""" + inband_mgmt_interface: str | None + """ + Pointer to interface used for inband management. + All configuration must be done using other data + models like network services or structured_config. + 'inband_mgmt_interface' is only used to refer to + this interface as source in various management protocol settings (future feature). + + On L2 switches, + this defaults to Vlan if either 'inband_mgmt_subnet' or 'inband_mgmt_ip' is set. + """ + inband_mgmt_vlan: int + """ + VLAN number used for inband management on L2 switches (switches using port-channel trunks as + uplinks). + When using 'inband_mgmt_subnet' the VLAN and SVIs will be created automatically on this + switch as well as all 'uplink_switches'. + When using 'inband_mgmt_ip' the VLAN and SVI will only be + created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be + created using network services data models. + + Default value: `4092` + """ + inband_mgmt_subnet: str | None + """ + Optional IP subnet assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ip virtual-router" and host-route injection based on + ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + + 3 + + GW on l2leafs : + 1 + Assign range larger than total l2leafs + 5 + Setting is ignored if 'inband_mgmt_ip' is set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + """ + inband_mgmt_ip: str | None + """ + IP address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_subnet', hence all behavior of 'inband_mgmt_subnet' is removed. + + If this is set the + VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN and SVI on + the parent switches must be created using network services data models. + + This setting is applicable + to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_gateway: str | None + """ + Default gateway configured in the 'inband_mgmt_vrf' when using 'inband_mgmt_ip'. Otherwise gateway + is derived from 'inband_mgmt_subnet' if set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_address: str | None + """ + IPv6 address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_ipv6_subnet', hence the configuration of 'inband_mgmt_ipv6_subnet' is ignored. + + If this + is set the VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN + and SVI on the parent switches must be created using network services data models. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_subnet: str | None + """ + Optional IPv6 prefix assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ipv6 virtual-router" and host-route injection based + on ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN + extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + 3 + + GW on l2leafs : + 1 + Assign range larger than + total l2leafs + 5 + + Setting is ignored if 'inband_mgmt_ipv6_address' is set. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_gateway: str | None + """ + Default gateway configured in the 'inband_mgmt_vrf'. + Used when `inband_mgmt_ipv6_address` is set. + Ignored when 'inband_mgmt_ipv6_subnet' is set (first IP in subnet used as gateway). + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_description: str + """ + Description configured on the Inband Management SVI. + + This setting is only applied on the devices + where it is set, it does not automatically affect any parent/child devices configuration, so it must + be set on each applicable node/node-group/node-type as needed. + + Default value: `"Inband Management"` + """ + inband_mgmt_vlan_name: str + """ + Name configured on the Inband Management VLAN. + This setting is only applied on the devices where it + is set, it does not automatically affect any parent/child devices configuration, so it must be set + on each applicable node/node-group/node-type as needed. + + Default value: `"INBAND_MGMT"` + """ + inband_mgmt_vrf: str + """ + VRF configured on the Inband Management Interface. + The VRF is created if not already created by + other means. + This setting is only applied on the devices where it is set, it does not automatically + affect any parent/child devices configuration, so it must be set on each applicable node/node- + group/node-type as needed. + + Default value: `"default"` + """ + inband_mgmt_mtu: int + """ + MTU configured on the Inband Management Interface. + This setting is only applied on the devices where + it is set, it does not automatically affect any parent/child devices configuration, so it must be + set on each applicable node/node-group/node-type as needed. + + Default value: `1500` + """ + inband_ztp: bool + """ + Enable to configure upstream device with proper configuration to allow downstream devices to be + Zero-Touch-Provisioned over the uplink interfaces. + For L2 devices this setting also requires that + the `inband_mgmt_vlan` is set for the node. + + PREVIEW: Support for L3 devices is marked as "preview", + meaning the data models or generated configuration can change at any time. + + Default value: `False` + """ + inband_ztp_lacp_fallback_delay: int + """ + Set the LACP fallback timeout of the upstream device's port-channel towards the downstream inband + ZTP node. + This setting also requires that `inband_ztp` is set for the node. + + Default value: `30` + """ + mpls_overlay_role: Literal["client", "server", "none"] | None + """ + Set the default mpls overlay role. + Acting role in overlay control plane. + """ + overlay_address_families: OverlayAddressFamilies + """ + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + """ + mpls_route_reflectors: MplsRouteReflectors + """ + List of inventory hostname acting as MPLS route-reflectors. + + Subclass of AvdList with `str` items. + """ + bgp_cluster_id: str | None + """Set BGP cluster id.""" + ptp: Ptp + """Subclass of AvdModel.""" + wan_role: Literal["client", "server"] | None + """ + Override the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + """ + cv_pathfinder_transit_mode: Literal["region", "zone"] | None + """ + Configure the transit mode for a WAN client for CV Pathfinder designs + only when the `wan_mode` root + key is set to `cv_pathfinder`. + + 'zone' is currently not supported. + """ + cv_pathfinder_region: str | None + """ + The CV Pathfinder region name. + This key is required for WAN routers but optional for pathfinders. + The region name must be defined under 'cv_pathfinder_regions'. + """ + cv_pathfinder_site: str | None + """ + The CV Pathfinder site name. + This key is required for WAN routers but optional for pathfinders. + For + WAN routers and pathfinders with `cv_pathfinder_region`, the site name must be defined for the + relevant region under 'cv_pathfinder_regions'. + For pathfinders without `cv_pathfinder_region` set, + the site must be defined under `cv_pathfinder_global_sites`. + """ + wan_ha: WanHa + """ + PREVIEW: This key is currently not supported + + The key is supported only if `wan_mode` == `cv- + pathfinder`. + AutoVPN support is still to be determined. + + Maximum 2 devices supported by group for + HA. + + Subclass of AvdModel. + """ + dps_mss_ipv4: str + """ + IPv4 MSS value configured under "router path-selection" on WAN Devices. + + Default value: `"auto"` + """ + l3_interfaces: L3Interfaces + """ + L3 Interfaces to configure on the node. + Used to define the node for WAN interfaces when + `wan_carrier` is set. + + Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is + `name` (`str`). + """ + data_plane_cpu_allocation_max: int | None + """ + Set the maximum number of CPU used for the data plane. + This setting is useful on virtual Route + Reflectors and Pathfinders where more CPU cores should be allocated for control plane. + """ + flow_tracker_type: Literal["sampled", "hardware"] | None + """ + Set the flow tracker type. + Override the `default_flow_tracker_type`` set at the `node_type_key` + level. + `default_flow_tracker_type` default value is `sampled`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + downlink_pools: DownlinkPools | UndefinedType = Undefined, + id: int | None | UndefinedType = Undefined, + platform: str | None | UndefinedType = Undefined, + mac_address: str | None | UndefinedType = Undefined, + system_mac_address: str | None | UndefinedType = Undefined, + serial_number: str | None | UndefinedType = Undefined, + rack: str | None | UndefinedType = Undefined, + mgmt_ip: str | None | UndefinedType = Undefined, + mgmt_gateway: str | None | UndefinedType = Undefined, + ipv6_mgmt_ip: str | None | UndefinedType = Undefined, + ipv6_mgmt_gateway: str | None | UndefinedType = Undefined, + mgmt_interface: str | None | UndefinedType = Undefined, + link_tracking: LinkTracking | UndefinedType = Undefined, + lacp_port_id_range: LacpPortIdRange | UndefinedType = Undefined, + always_configure_ip_routing: bool | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None | UndefinedType = Undefined, + uplink_ipv4_pool: str | None | UndefinedType = Undefined, + uplink_interfaces: UplinkInterfaces | UndefinedType = Undefined, + uplink_switch_interfaces: UplinkSwitchInterfaces | UndefinedType = Undefined, + uplink_switches: UplinkSwitches | UndefinedType = Undefined, + uplink_interface_speed: str | None | UndefinedType = Undefined, + 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 | UndefinedType = Undefined, + uplink_bfd: bool | UndefinedType = Undefined, + uplink_native_vlan: int | None | UndefinedType = Undefined, + uplink_ptp: UplinkPtp | UndefinedType = Undefined, + uplink_macsec: UplinkMacsec | UndefinedType = Undefined, + uplink_port_channel_id: int | None | UndefinedType = Undefined, + uplink_switch_port_channel_id: int | None | UndefinedType = Undefined, + uplink_structured_config: dict | UndefinedType = Undefined, + mlag_port_channel_structured_config: MlagPortChannelStructuredConfig | UndefinedType = Undefined, + mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig | UndefinedType = Undefined, + mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig | UndefinedType = Undefined, + short_esi: str | None | UndefinedType = Undefined, + isis_system_id_prefix: str | None | UndefinedType = Undefined, + isis_maximum_paths: int | None | UndefinedType = Undefined, + is_type: Literal["level-1-2", "level-1", "level-2"] | None | UndefinedType = Undefined, + node_sid_base: int | UndefinedType = Undefined, + loopback_ipv4_pool: str | None | UndefinedType = Undefined, + loopback_ipv4_address: str | None | UndefinedType = Undefined, + vtep_loopback_ipv4_pool: str | None | UndefinedType = Undefined, + vtep_loopback_ipv4_address: str | None | UndefinedType = Undefined, + loopback_ipv4_offset: int | UndefinedType = Undefined, + loopback_ipv6_pool: str | None | UndefinedType = Undefined, + loopback_ipv6_offset: int | UndefinedType = Undefined, + vtep: bool | None | UndefinedType = Undefined, + vtep_loopback: str | None | UndefinedType = Undefined, + bgp_as: str | None | UndefinedType = Undefined, + bgp_defaults: BgpDefaults | UndefinedType = Undefined, + evpn_role: Literal["client", "server", "none"] | None | UndefinedType = Undefined, + evpn_route_servers: EvpnRouteServers | UndefinedType = Undefined, + evpn_services_l2_only: bool | UndefinedType = Undefined, + filter: Filter | UndefinedType = Undefined, + igmp_snooping_enabled: bool | None | UndefinedType = Undefined, + evpn_gateway: EvpnGateway | UndefinedType = Undefined, + ipvpn_gateway: IpvpnGateway | UndefinedType = Undefined, + mlag: bool | UndefinedType = Undefined, + mlag_dual_primary_detection: bool | UndefinedType = Undefined, + mlag_ibgp_origin_incomplete: bool | UndefinedType = Undefined, + mlag_interfaces: MlagInterfaces | UndefinedType = Undefined, + mlag_interfaces_speed: str | None | UndefinedType = Undefined, + mlag_peer_l3_vlan: int | UndefinedType = Undefined, + mlag_peer_l3_ipv4_pool: str | None | UndefinedType = Undefined, + mlag_peer_vlan: int | UndefinedType = Undefined, + mlag_peer_link_allowed_vlans: str | None | UndefinedType = Undefined, + mlag_peer_address_family: Literal["ipv4", "ipv6"] | UndefinedType = Undefined, + mlag_peer_ipv4_pool: str | None | UndefinedType = Undefined, + mlag_peer_ipv6_pool: str | None | UndefinedType = Undefined, + mlag_port_channel_id: int | None | UndefinedType = Undefined, + mlag_domain_id: str | None | UndefinedType = Undefined, + spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None | UndefinedType = Undefined, + spanning_tree_priority: int | UndefinedType = Undefined, + spanning_tree_root_super: bool | UndefinedType = Undefined, + virtual_router_mac_address: str | None | UndefinedType = Undefined, + inband_mgmt_interface: str | None | UndefinedType = Undefined, + inband_mgmt_vlan: int | UndefinedType = Undefined, + inband_mgmt_subnet: str | None | UndefinedType = Undefined, + inband_mgmt_ip: str | None | UndefinedType = Undefined, + inband_mgmt_gateway: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_address: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_subnet: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_gateway: str | None | UndefinedType = Undefined, + inband_mgmt_description: str | UndefinedType = Undefined, + inband_mgmt_vlan_name: str | UndefinedType = Undefined, + inband_mgmt_vrf: str | UndefinedType = Undefined, + inband_mgmt_mtu: int | UndefinedType = Undefined, + inband_ztp: bool | UndefinedType = Undefined, + inband_ztp_lacp_fallback_delay: int | UndefinedType = Undefined, + mpls_overlay_role: Literal["client", "server", "none"] | None | UndefinedType = Undefined, + overlay_address_families: OverlayAddressFamilies | UndefinedType = Undefined, + mpls_route_reflectors: MplsRouteReflectors | UndefinedType = Undefined, + bgp_cluster_id: str | None | UndefinedType = Undefined, + ptp: Ptp | UndefinedType = Undefined, + wan_role: Literal["client", "server"] | None | UndefinedType = Undefined, + cv_pathfinder_transit_mode: Literal["region", "zone"] | None | UndefinedType = Undefined, + cv_pathfinder_region: str | None | UndefinedType = Undefined, + cv_pathfinder_site: str | None | UndefinedType = Undefined, + wan_ha: WanHa | UndefinedType = Undefined, + dps_mss_ipv4: str | UndefinedType = Undefined, + l3_interfaces: L3Interfaces | UndefinedType = Undefined, + data_plane_cpu_allocation_max: int | None | UndefinedType = Undefined, + flow_tracker_type: Literal["sampled", "hardware"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NodesItem. + + + Subclass of AvdModel. + + Args: + name: The Node Name is used as "hostname". + downlink_pools: + IPv4 pools used for links to downlink switches. Set this on the parent switch. Cannot be combined + with `uplink_ipv4_pool` set on the downlink switch. + + Subclass of AvdList with `DownlinkPoolsItem` + items. + id: Unique identifier used for IP addressing and other algorithms. + platform: Arista platform family. + mac_address: Leverage to document management interface mac address. + system_mac_address: + System MAC Address in this following format: "xx:xx:xx:xx:xx:xx". + Set to the same MAC address as + available in "show version" on the device. + "system_mac_address" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + serial_number: + Set to the Serial Number of the device. + Only used for documentation purpose in the fabric + documentation and part of the structured_config. + "serial_number" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + rack: Rack that the switch is located in (only used in snmp_settings location). + mgmt_ip: Node management interface IPv4 address. + mgmt_gateway: + This key sets the management gateway for the device. It takes precedence over the global + `mgmt_gateway`. + ipv6_mgmt_ip: Node management interface IPv6 address. + ipv6_mgmt_gateway: + This key sets the ipv6 management gateway for the device. It takes precedence over the global + `ipv6_mgmt_gateway`. + mgmt_interface: + Management Interface Name. + Default -> platform_management_interface -> mgmt_interface -> + "Management1". + link_tracking: + This configures the Link Tracking Group on a switch as well as adds the p2p-uplinks of the switch as + the upstream interfaces. + Useful in EVPN multhoming designs. + + + Subclass of AvdModel. + lacp_port_id_range: + This will generate the "lacp port-id range", "begin" and "end" values based on node "id" and the + number of nodes in the "node_group". + Unique LACP port-id ranges are recommended for EVPN Multihoming + designs. + + + Subclass of AvdModel. + always_configure_ip_routing: + Force configuration of "ip routing" even on L2 devices. + Use this to retain behavior of AVD versions + below 4.0.0. + raw_eos_cli: EOS CLI rendered directly on the root level of the final EOS configuration. + structured_config: + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + uplink_type: + Override the default `uplink_type` set at the `node_type_key` level. + `uplink_type` must be "p2p" if + `vtep` or `underlay_router` is true for the `node_type_key` definition. + uplink_ipv4_pool: IPv4 subnet to use to connect to uplink switches. + uplink_interfaces: + Local uplink interfaces. + Each list item supports range syntax that can be expanded into a list of + interfaces. + If uplink_interfaces is not defined, platform-specific defaults (defined under + default_interfaces) will be used instead. + Please note that default_interfaces are not defined by + default, you should define these yourself. + + + Subclass of AvdList with `str` items. + uplink_switch_interfaces: + Interfaces located on uplink switches. + + Subclass of AvdList with `str` items. + uplink_switches: Subclass of AvdList with `str` items. + uplink_interface_speed: + Set point-to-Point interface speed and will apply to uplink interfaces on both ends. + (Uplink switch + interface speed can be overridden with `uplink_switch_interface_speed`). + Speed should be set in the + format `` or `forced ` or `auto `. + uplink_switch_interface_speed: + 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: Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting. + max_uplink_switches: + 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: + 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: Enable bfd on uplink interfaces. + uplink_native_vlan: + 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: + Enable PTP on all infrastructure links. + + Subclass of AvdModel. + uplink_macsec: + Enable MacSec on all uplinks. + + Subclass of AvdModel. + uplink_port_channel_id: + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink Port-channel + ID will be set to the number of the lowest member interface defined under `uplink_interfaces`. + For + example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ Eth11/1, Eth22/1 ] -> ID 111 + For + MLAG port-channels ID will be based on the lowest member interface on the first MLAG switch. + This + option overrides the default behavior and statically sets the local Port-channel ID. + Note! Make sure + the ID is unique and does not overlap with autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between 1 and 2000 and both MLAG switches must have the same + value. + uplink_switch_port_channel_id: + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink switch Port- + channel ID will be set to the number of the first interface defined under + `uplink_switch_interfaces`. + For example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ + Eth11/1, Eth22/1 ] -> ID 111 + For MLAG port-channels ID will be based on the lowest member interface + on the first MLAG switch. + This option overrides the default behavior and statically sets the Port- + channel ID on the uplink switch. + Note! Make sure the ID is unique and does not overlap with + autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between + 1 and 2000 and both MLAG switches must have the same value. + uplink_structured_config: + Custom structured config applied to "uplink_interfaces", and "uplink_switch_interfaces". + When + uplink_type == "p2p", custom structured config added under ethernet_interfaces.[name=] + for eos_cli_config_gen overrides the settings on the ethernet interface level. + When uplink_type == + "port-channel", custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen overrides the settings on the port-channel interface level. + "uplink_structured_config" is applied after "structured_config", so it can override + "structured_config" defined on node-level. + Note! The content of this dictionary is _not_ validated + by the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + mlag_port_channel_structured_config: + Custom structured config applied to MLAG peer link port-channel id. + Added under + port_channel_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the + port-channel interface level. + "mlag_port_channel_structured_config" is applied after + "structured_config", so it can override "structured_config" defined on node-level. + + + Subclass of + AvdModel. + mlag_peer_vlan_structured_config: + Custom structured config applied to MLAG Peer Link (control link) SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_vlan_structured_config" is applied after "structured_config", so it can + override "structured_config" defined on node-level. + + + Subclass of AvdModel. + mlag_peer_l3_vlan_structured_config: + Custom structured config applied to MLAG underlay L3 peering SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_l3_vlan_structured_config" is applied after "structured_config", so it + can override "structured_config" defined on node-level. + + + Subclass of AvdModel. + short_esi: + short_esi only valid for l2leaf devices using port-channel uplink. + Setting short_esi to "auto" + generates the short_esi automatically using a hash of configuration elements. + < 0000:0000:0000 | + auto >. + isis_system_id_prefix: (4.4 hexadecimal). + isis_maximum_paths: Number of path to configure in ECMP for ISIS. + is_type: Overrides `isis_default_is_type`. + node_sid_base: Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID. + loopback_ipv4_pool: IPv4 subnet for Loopback0 allocation. + loopback_ipv4_address: + IPv4 address without mask for Loopback0. + When set, it takes precedence over `loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not catch duplicates. + vtep_loopback_ipv4_pool: IPv4 subnet for VTEP-Loopback allocation. + vtep_loopback_ipv4_address: + IPv4 address without mask for VTEP-Loopback. + When set, it takes precedence over + `vtep_loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not + catch duplicates. + loopback_ipv4_offset: + Offset all assigned loopback IP addresses. + Required when the < loopback_ipv4_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid over-lapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv4_offset: < total # spine switches > or vice versa. + loopback_ipv6_pool: IPv6 subnet for Loopback0 allocation. + loopback_ipv6_offset: + Offset all assigned loopback IPv6 addresses. + Required when the < loopback_ipv6_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid overlapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv6_offset: < total # spine switches > or vice versa. + vtep: + Node is configured as a VTEP when applicable based on 'overlay_routing_protocol'. + Overrides VTEP + setting inherited from node_type_keys. + vtep_loopback: Set VXLAN source interface. + bgp_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + Required with eBGP. + bgp_defaults: + List of EOS commands to apply to BGP daemon. + + Subclass of AvdList with `str` items. + evpn_role: + Acting role in EVPN control plane. + Default is set in node_type definition from node_type_keys. + evpn_route_servers: + List of nodes acting as EVPN Route-Servers / Route-Reflectors. + + Subclass of AvdList with `str` + items. + evpn_services_l2_only: + Possibility to prevent configuration of Tenant VRFs and SVIs. + Override node definition + "network_services_l3" from node_type_keys. + This allows support for centralized routing. + filter: + Filter L3 and L2 network services based on tenant and tags (and operation filter). + If filter is not + defined it will default to all. + + + Subclass of AvdModel. + igmp_snooping_enabled: Activate or deactivate IGMP snooping on device level. + evpn_gateway: + Node is acting as EVPN Multi-Domain Gateway. + New BGP peer-group is generated between EVPN GWs in + different domains or between GWs and Route Servers. + Name can be changed under + "bgp_peer_groups.evpn_overlay_core" variable. + L3 rechability for different EVPN GWs must be already + in place, it is recommended to use DCI & L3 Edge if Route Servers and GWs are not defined under the + same Ansible inventory. + + + Subclass of AvdModel. + ipvpn_gateway: + Node is acting as IP-VPN Gateway for EVPN to MPLS-IP-VPN Interworking. The BGP peer group used for + this is "bgp_peer_groups.ipvpn_gateway_peers". + L3 Reachability is required for this to work, the + preferred method to establish underlay connectivity is to use core_interfaces. + + + Subclass of + AvdModel. + mlag: Enable / Disable auto MLAG, when two nodes are defined in node group. + mlag_dual_primary_detection: Enable / Disable MLAG dual primary detection. + mlag_ibgp_origin_incomplete: + Set origin of routes received from MLAG iBGP peer to incomplete. + The purpose is to optimize routing + for leaf loopbacks from spine perspective and + avoid suboptimal routing via peerlink for control + plane traffic. + mlag_interfaces: + Each list item supports range syntax that can be expanded into a list of interfaces. + Required when + MLAG leafs are present in the topology. + + + Subclass of AvdList with `str` items. + mlag_interfaces_speed: + Set MLAG interface speed. + Speed should be set in the format `` or `forced + ` or `auto `. + mlag_peer_l3_vlan: + Underlay L3 peering SVI interface id. + If set to 0 or the same vlan as mlag_peer_vlan, the + mlag_peer_vlan will be used for L3 peering. + mlag_peer_l3_ipv4_pool: + IP address pool used for MLAG underlay L3 peering. IP is derived from the node id. + Required when + MLAG leafs present in topology and they are using a separate L3 peering VLAN. + mlag_peer_vlan: MLAG Peer Link (control link) SVI interface id. + mlag_peer_link_allowed_vlans: mlag_peer_link_allowed_vlans + mlag_peer_address_family: + IP address family used to establish MLAG Peer Link (control link). + `ipv6` requires EOS version + 4.31.1F or higher. + Note: `ipv6` is not supported in combination with a common MLAG peer link VLAN + (ex. `mlag_peer_l3_vlan` set to 4094). + mlag_peer_ipv4_pool: + IPv4 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv4` (default). + mlag_peer_ipv6_pool: + IPv6 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv6`. + mlag_port_channel_id: + If not set, the mlag port-channel id is generated based on the digits of the first interface present + in 'mlag_interfaces'. + Valid port-channel id numbers are < 1-2000 > for EOS < 4.25.0F and < 1 - + 999999 > for EOS >= 4.25.0F. + mlag_domain_id: MLAG Domain ID. If not set the node group name (Set with "group" key) will be used. + spanning_tree_mode: spanning_tree_mode + spanning_tree_priority: + Spanning-tree priority configured for the selected mode. + For `rapid-pvst` the priority can also be + set per VLAN under network services. + spanning_tree_root_super: spanning_tree_root_super + virtual_router_mac_address: Virtual router mac address for anycast gateway. + inband_mgmt_interface: + Pointer to interface used for inband management. + All configuration must be done using other data + models like network services or structured_config. + 'inband_mgmt_interface' is only used to refer to + this interface as source in various management protocol settings (future feature). + + On L2 switches, + this defaults to Vlan if either 'inband_mgmt_subnet' or 'inband_mgmt_ip' is set. + inband_mgmt_vlan: + VLAN number used for inband management on L2 switches (switches using port-channel trunks as + uplinks). + When using 'inband_mgmt_subnet' the VLAN and SVIs will be created automatically on this + switch as well as all 'uplink_switches'. + When using 'inband_mgmt_ip' the VLAN and SVI will only be + created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be + created using network services data models. + inband_mgmt_subnet: + Optional IP subnet assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ip virtual-router" and host-route injection based on + ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + + 3 + + GW on l2leafs : + 1 + Assign range larger than total l2leafs + 5 + Setting is ignored if 'inband_mgmt_ip' is set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + inband_mgmt_ip: + IP address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_subnet', hence all behavior of 'inband_mgmt_subnet' is removed. + + If this is set the + VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN and SVI on + the parent switches must be created using network services data models. + + This setting is applicable + to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_gateway: + Default gateway configured in the 'inband_mgmt_vrf' when using 'inband_mgmt_ip'. Otherwise gateway + is derived from 'inband_mgmt_subnet' if set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + inband_mgmt_ipv6_address: + IPv6 address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_ipv6_subnet', hence the configuration of 'inband_mgmt_ipv6_subnet' is ignored. + + If this + is set the VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN + and SVI on the parent switches must be created using network services data models. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_ipv6_subnet: + Optional IPv6 prefix assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ipv6 virtual-router" and host-route injection based + on ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN + extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + 3 + + GW on l2leafs : + 1 + Assign range larger than + total l2leafs + 5 + + Setting is ignored if 'inband_mgmt_ipv6_address' is set. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_ipv6_gateway: + Default gateway configured in the 'inband_mgmt_vrf'. + Used when `inband_mgmt_ipv6_address` is set. + Ignored when 'inband_mgmt_ipv6_subnet' is set (first IP in subnet used as gateway). + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_description: + Description configured on the Inband Management SVI. + + This setting is only applied on the devices + where it is set, it does not automatically affect any parent/child devices configuration, so it must + be set on each applicable node/node-group/node-type as needed. + inband_mgmt_vlan_name: + Name configured on the Inband Management VLAN. + This setting is only applied on the devices where it + is set, it does not automatically affect any parent/child devices configuration, so it must be set + on each applicable node/node-group/node-type as needed. + inband_mgmt_vrf: + VRF configured on the Inband Management Interface. + The VRF is created if not already created by + other means. + This setting is only applied on the devices where it is set, it does not automatically + affect any parent/child devices configuration, so it must be set on each applicable node/node- + group/node-type as needed. + inband_mgmt_mtu: + MTU configured on the Inband Management Interface. + This setting is only applied on the devices where + it is set, it does not automatically affect any parent/child devices configuration, so it must be + set on each applicable node/node-group/node-type as needed. + inband_ztp: + Enable to configure upstream device with proper configuration to allow downstream devices to be + Zero-Touch-Provisioned over the uplink interfaces. + For L2 devices this setting also requires that + the `inband_mgmt_vlan` is set for the node. + + PREVIEW: Support for L3 devices is marked as "preview", + meaning the data models or generated configuration can change at any time. + inband_ztp_lacp_fallback_delay: + Set the LACP fallback timeout of the upstream device's port-channel towards the downstream inband + ZTP node. + This setting also requires that `inband_ztp` is set for the node. + mpls_overlay_role: + Set the default mpls overlay role. + Acting role in overlay control plane. + overlay_address_families: + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + mpls_route_reflectors: + List of inventory hostname acting as MPLS route-reflectors. + + Subclass of AvdList with `str` items. + bgp_cluster_id: Set BGP cluster id. + ptp: Subclass of AvdModel. + wan_role: + Override the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + cv_pathfinder_transit_mode: + Configure the transit mode for a WAN client for CV Pathfinder designs + only when the `wan_mode` root + key is set to `cv_pathfinder`. + + 'zone' is currently not supported. + cv_pathfinder_region: + The CV Pathfinder region name. + This key is required for WAN routers but optional for pathfinders. + The region name must be defined under 'cv_pathfinder_regions'. + cv_pathfinder_site: + The CV Pathfinder site name. + This key is required for WAN routers but optional for pathfinders. + For + WAN routers and pathfinders with `cv_pathfinder_region`, the site name must be defined for the + relevant region under 'cv_pathfinder_regions'. + For pathfinders without `cv_pathfinder_region` set, + the site must be defined under `cv_pathfinder_global_sites`. + wan_ha: + PREVIEW: This key is currently not supported + + The key is supported only if `wan_mode` == `cv- + pathfinder`. + AutoVPN support is still to be determined. + + Maximum 2 devices supported by group for + HA. + + Subclass of AvdModel. + dps_mss_ipv4: IPv4 MSS value configured under "router path-selection" on WAN Devices. + l3_interfaces: + L3 Interfaces to configure on the node. + Used to define the node for WAN interfaces when + `wan_carrier` is set. + + Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is + `name` (`str`). + data_plane_cpu_allocation_max: + Set the maximum number of CPU used for the data plane. + This setting is useful on virtual Route + Reflectors and Pathfinders where more CPU cores should be allocated for control plane. + flow_tracker_type: + Set the flow tracker type. + Override the `default_flow_tracker_type`` set at the `node_type_key` + level. + `default_flow_tracker_type` default value is `sampled`. + _custom_data: _custom_data + + """ + + class Nodes(AvdIndexedList[str, NodesItem]): + """Subclass of AvdIndexedList with `NodesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Nodes._item_type = NodesItem + + class LinkTracking(AvdModel): + """Subclass of AvdModel.""" + + class GroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "recovery_delay": {"type": int}, + "links_minimum": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str | None + """Tracking group name.""" + recovery_delay: int | None + """default -> platform_settings_mlag_reload_delay -> 300.""" + links_minimum: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + recovery_delay: int | None | UndefinedType = Undefined, + links_minimum: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GroupsItem. + + + Subclass of AvdModel. + + Args: + name: Tracking group name. + recovery_delay: default -> platform_settings_mlag_reload_delay -> 300. + links_minimum: links_minimum + _custom_data: _custom_data + + """ + + class Groups(AvdList[GroupsItem]): + """Subclass of AvdList with `GroupsItem` items.""" + + Groups._item_type = GroupsItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "groups": {"type": Groups, "default": lambda cls: coerce_type([{"name": "LT_GROUP1"}], target_type=cls)}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + groups: Groups + """ + Link Tracking Groups. + By default a single group named "LT_GROUP1" is defined with default values. + Any groups defined under "groups" will replace the default. + + + Subclass of AvdList with `GroupsItem` + items. + + Default value: `lambda cls: coerce_type([{"name": "LT_GROUP1"}], target_type=cls)` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + groups: + Link Tracking Groups. + By default a single group named "LT_GROUP1" is defined with default values. + Any groups defined under "groups" will replace the default. + + + Subclass of AvdList with `GroupsItem` + items. + _custom_data: _custom_data + + """ + + class LacpPortIdRange(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "size": {"type": int, "default": 128}, + "offset": {"type": int, "default": 0}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + size: int + """ + Recommended size > = number of ports in the switch. + + Default value: `128` + """ + offset: int + """ + Offset is used to avoid overlapping port-id ranges of different switches. + Useful when a "connected- + endpoint" is connected to switches in different "node_groups". + + Default value: `0` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + size: int | UndefinedType = Undefined, + offset: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LacpPortIdRange. + + + Subclass of AvdModel. + + Args: + enabled: enabled + size: Recommended size > = number of ports in the switch. + offset: + Offset is used to avoid overlapping port-id ranges of different switches. + Useful when a "connected- + endpoint" is connected to switches in different "node_groups". + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen): + """Subclass of AvdModel.""" + + class UplinkInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkInterfaces._item_type = str + + class UplinkSwitchInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkSwitchInterfaces._item_type = str + + class UplinkSwitches(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkSwitches._item_type = str + + class UplinkPtp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enable": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enable: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, enable: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + UplinkPtp. + + + Subclass of AvdModel. + + Args: + enable: enable + _custom_data: _custom_data + + """ + + class UplinkMacsec(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "_custom_data": {"type": dict}} + profile: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, profile: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + UplinkMacsec. + + + Subclass of AvdModel. + + Args: + profile: profile + _custom_data: _custom_data + + """ + + class MlagPortChannelStructuredConfig(EosCliConfigGen.PortChannelInterfacesItem): + """Subclass of AvdModel.""" + + class MlagPeerVlanStructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + class MlagPeerL3VlanStructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + class BgpDefaults(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + BgpDefaults._item_type = str + + class EvpnRouteServers(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + EvpnRouteServers._item_type = str + + class Filter(AvdModel): + """Subclass of AvdModel.""" + + class Tenants(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tenants._item_type = str + + class Tags(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tags._item_type = str + + class AllowVrfs(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AllowVrfs._item_type = str + + class DenyVrfs(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DenyVrfs._item_type = str + + class AlwaysIncludeVrfsInTenants(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AlwaysIncludeVrfsInTenants._item_type = str + + _fields: ClassVar[dict] = { + "tenants": {"type": Tenants, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "tags": {"type": Tags, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "allow_vrfs": {"type": AllowVrfs, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "deny_vrfs": {"type": DenyVrfs, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "always_include_vrfs_in_tenants": {"type": AlwaysIncludeVrfsInTenants}, + "only_vlans_in_use": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + tenants: Tenants + """ + Limit configured Network Services to those defined under these Tenants. Set to ['all'] for all + Tenants (default). + This list also limits Tenants included by `always_include_vrfs_in_tenants`. + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + tags: Tags + """ + Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default). + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + allow_vrfs: AllowVrfs + """ + Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs + (default). + This list also limits VRFs included by `always_include_vrfs_in_tenants`. + + Subclass of + AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + deny_vrfs: DenyVrfs + """ + Prevent configuration of Network Services defined under these VRFs. + This list prevents the given + VRFs to be included by any other filtering mechanism. + + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + always_include_vrfs_in_tenants: AlwaysIncludeVrfsInTenants + """ + List of tenants where VRFs will be configured even if VLANs are not included in tags. + Useful for L3 + "border" leaf. + + + Subclass of AvdList with `str` items. + """ + only_vlans_in_use: bool + """ + Only configure VLANs, SVIs, VRFs in use by connected endpoints or downstream L2 switches. + Note! This + feature only considers configuration managed by eos_designs. + This excludes structured_config, + custom_structured_configuration_, raw_eos_cli, eos_cli, custom templates, configlets etc. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + tenants: Tenants | UndefinedType = Undefined, + tags: Tags | UndefinedType = Undefined, + allow_vrfs: AllowVrfs | UndefinedType = Undefined, + deny_vrfs: DenyVrfs | UndefinedType = Undefined, + always_include_vrfs_in_tenants: AlwaysIncludeVrfsInTenants | UndefinedType = Undefined, + only_vlans_in_use: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Filter. + + + Subclass of AvdModel. + + Args: + tenants: + Limit configured Network Services to those defined under these Tenants. Set to ['all'] for all + Tenants (default). + This list also limits Tenants included by `always_include_vrfs_in_tenants`. + Subclass of AvdList with `str` items. + tags: + Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default). + Subclass of AvdList with `str` items. + allow_vrfs: + Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs + (default). + This list also limits VRFs included by `always_include_vrfs_in_tenants`. + + Subclass of + AvdList with `str` items. + deny_vrfs: + Prevent configuration of Network Services defined under these VRFs. + This list prevents the given + VRFs to be included by any other filtering mechanism. + + Subclass of AvdList with `str` items. + always_include_vrfs_in_tenants: + List of tenants where VRFs will be configured even if VLANs are not included in tags. + Useful for L3 + "border" leaf. + + + Subclass of AvdList with `str` items. + only_vlans_in_use: + Only configure VLANs, SVIs, VRFs in use by connected endpoints or downstream L2 switches. + Note! This + feature only considers configuration managed by eos_designs. + This excludes structured_config, + custom_structured_configuration_, raw_eos_cli, eos_cli, custom templates, configlets etc. + _custom_data: _custom_data + + """ + + class EvpnGateway(AvdModel): + """Subclass of AvdModel.""" + + class RemotePeersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hostname": {"type": str}, + "ip_address": {"type": str}, + "bgp_as": {"type": str}, + "_custom_data": {"type": dict}, + } + hostname: str + """Hostname of remote EVPN GW server.""" + ip_address: str | None + """Peering IP of remote Route Server.""" + bgp_as: str | None + """ + Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being + interpreted as a float number. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: str | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + bgp_as: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemotePeersItem. + + + Subclass of AvdModel. + + Args: + hostname: Hostname of remote EVPN GW server. + ip_address: Peering IP of remote Route Server. + bgp_as: + Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being + interpreted as a float number. + _custom_data: _custom_data + + """ + + class RemotePeers(AvdIndexedList[str, RemotePeersItem]): + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + + _primary_key: ClassVar[str] = "hostname" + + RemotePeers._item_type = RemotePeersItem + + class EvpnL2(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enabled: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, enabled: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + EvpnL2. + + + Subclass of AvdModel. + + Args: + enabled: enabled + _custom_data: _custom_data + + """ + + class EvpnL3(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "inter_domain": {"type": bool, "default": True}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + inter_domain: bool + """Default value: `True`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + inter_domain: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnL3. + + + Subclass of AvdModel. + + Args: + enabled: enabled + inter_domain: inter_domain + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "remote_peers": {"type": RemotePeers}, + "evpn_l2": {"type": EvpnL2}, + "evpn_l3": {"type": EvpnL3}, + "_custom_data": {"type": dict}, + } + remote_peers: RemotePeers + """ + Define remote peers of the EVPN VXLAN Gateway. + If the hostname can be found in the inventory, + ip_address and BGP ASN will be automatically populated. Manual override takes precedence. + If the + peer's hostname can not be found in the inventory, ip_address and bgp_as must be defined. + + + Subclass + of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + """ + evpn_l2: EvpnL2 + """ + Enable EVPN Gateway functionality for route-types 2 (MAC-IP) and 3 (IMET). + + Subclass of AvdModel. + """ + evpn_l3: EvpnL3 + """ + Enable EVPN Gateway functionality for route-type 5 (IP-PREFIX). + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + remote_peers: RemotePeers | UndefinedType = Undefined, + evpn_l2: EvpnL2 | UndefinedType = Undefined, + evpn_l3: EvpnL3 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnGateway. + + + Subclass of AvdModel. + + Args: + remote_peers: + Define remote peers of the EVPN VXLAN Gateway. + If the hostname can be found in the inventory, + ip_address and BGP ASN will be automatically populated. Manual override takes precedence. + If the + peer's hostname can not be found in the inventory, ip_address and bgp_as must be defined. + + + Subclass + of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + evpn_l2: + Enable EVPN Gateway functionality for route-types 2 (MAC-IP) and 3 (IMET). + + Subclass of AvdModel. + evpn_l3: + Enable EVPN Gateway functionality for route-type 5 (IP-PREFIX). + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class IpvpnGateway(AvdModel): + """Subclass of AvdModel.""" + + class AddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AddressFamilies._item_type = str + + class RemotePeersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hostname": {"type": str}, + "ip_address": {"type": str}, + "bgp_as": {"type": str}, + "_custom_data": {"type": dict}, + } + hostname: str + """Hostname of remote IPVPN Peer.""" + ip_address: str + """Peering IP of remote IPVPN Peer.""" + bgp_as: str + """ + Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For + asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted + as a float number. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: str | UndefinedType = Undefined, + ip_address: str | UndefinedType = Undefined, + bgp_as: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemotePeersItem. + + + Subclass of AvdModel. + + Args: + hostname: Hostname of remote IPVPN Peer. + ip_address: Peering IP of remote IPVPN Peer. + bgp_as: + Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For + asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted + as a float number. + _custom_data: _custom_data + + """ + + class RemotePeers(AvdIndexedList[str, RemotePeersItem]): + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + + _primary_key: ClassVar[str] = "hostname" + + RemotePeers._item_type = RemotePeersItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "evpn_domain_id": {"type": str, "default": "65535:1"}, + "ipvpn_domain_id": {"type": str, "default": "65535:2"}, + "enable_d_path": {"type": bool, "default": True}, + "maximum_routes": {"type": int, "default": 0}, + "local_as": {"type": str}, + "address_families": {"type": AddressFamilies, "default": lambda cls: coerce_type(["vpn-ipv4"], target_type=cls)}, + "remote_peers": {"type": RemotePeers}, + "_custom_data": {"type": dict}, + } + enabled: bool + evpn_domain_id: str + """ + Domain ID to assign to EVPN address family for use with D-path. Format :. + + Default value: `"65535:1"` + """ + ipvpn_domain_id: str + """ + Domain ID to assign to IPVPN address families for use with D-path. Format :. + + Default value: `"65535:2"` + """ + enable_d_path: bool + """ + Enable D-path for use with BGP bestpath selection algorithm. + + Default value: `True` + """ + maximum_routes: int + """ + Maximum routes to accept from IPVPN remote peers. + + Default value: `0` + """ + local_as: str | None + """ + Local BGP AS applied to peering with IPVPN remote peers. + BGP AS <1-4294967295> or AS number in asdot + notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number. + """ + address_families: AddressFamilies + """ + IPVPN address families to enable for remote peers. + + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["vpn-ipv4"], target_type=cls)` + """ + remote_peers: RemotePeers + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + evpn_domain_id: str | UndefinedType = Undefined, + ipvpn_domain_id: str | UndefinedType = Undefined, + enable_d_path: bool | UndefinedType = Undefined, + maximum_routes: int | UndefinedType = Undefined, + local_as: str | None | UndefinedType = Undefined, + address_families: AddressFamilies | UndefinedType = Undefined, + remote_peers: RemotePeers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpvpnGateway. + + + Subclass of AvdModel. + + Args: + enabled: enabled + evpn_domain_id: Domain ID to assign to EVPN address family for use with D-path. Format :. + ipvpn_domain_id: Domain ID to assign to IPVPN address families for use with D-path. Format :. + enable_d_path: Enable D-path for use with BGP bestpath selection algorithm. + maximum_routes: Maximum routes to accept from IPVPN remote peers. + local_as: + Local BGP AS applied to peering with IPVPN remote peers. + BGP AS <1-4294967295> or AS number in asdot + notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number. + address_families: + IPVPN address families to enable for remote peers. + + Subclass of AvdList with `str` items. + remote_peers: Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + _custom_data: _custom_data + + """ + + class MlagInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MlagInterfaces._item_type = str + + class OverlayAddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + OverlayAddressFamilies._item_type = str + + class MplsRouteReflectors(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MplsRouteReflectors._item_type = str + + class Ptp(AvdModel): + """Subclass of AvdModel.""" + + class Dscp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"general_messages": {"type": int}, "event_messages": {"type": int}, "_custom_data": {"type": dict}} + general_messages: int | None + event_messages: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + general_messages: int | None | UndefinedType = Undefined, + event_messages: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dscp. + + + Subclass of AvdModel. + + Args: + general_messages: general_messages + event_messages: event_messages + _custom_data: _custom_data + + """ + + class Monitor(AvdModel): + """Subclass of AvdModel.""" + + class Threshold(AvdModel): + """Subclass of AvdModel.""" + + class Drop(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "offset_from_master": {"type": int}, + "mean_path_delay": {"type": int}, + "_custom_data": {"type": dict}, + } + offset_from_master: int | None + mean_path_delay: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + offset_from_master: int | None | UndefinedType = Undefined, + mean_path_delay: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Drop. + + + Subclass of AvdModel. + + Args: + offset_from_master: offset_from_master + mean_path_delay: mean_path_delay + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "offset_from_master": {"type": int, "default": 250}, + "mean_path_delay": {"type": int, "default": 1500}, + "drop": {"type": Drop}, + "_custom_data": {"type": dict}, + } + offset_from_master: int + """Default value: `250`""" + mean_path_delay: int + """Default value: `1500`""" + drop: Drop + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + offset_from_master: int | UndefinedType = Undefined, + mean_path_delay: int | UndefinedType = Undefined, + drop: Drop | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Threshold. + + + Subclass of AvdModel. + + Args: + offset_from_master: offset_from_master + mean_path_delay: mean_path_delay + drop: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MissingMessage(AvdModel): + """Subclass of AvdModel.""" + + class Intervals(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "announce": {"type": int}, + "follow_up": {"type": int}, + "sync": {"type": int}, + "_custom_data": {"type": dict}, + } + announce: int | None + follow_up: int | None + sync: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + announce: int | None | UndefinedType = Undefined, + follow_up: int | None | UndefinedType = Undefined, + sync: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Intervals. + + + Subclass of AvdModel. + + Args: + announce: announce + follow_up: follow_up + sync: sync + _custom_data: _custom_data + + """ + + class SequenceIds(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "announce": {"type": int, "default": 3}, + "delay_resp": {"type": int, "default": 3}, + "follow_up": {"type": int, "default": 3}, + "sync": {"type": int, "default": 3}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + announce: int + """Default value: `3`""" + delay_resp: int + """Default value: `3`""" + follow_up: int + """Default value: `3`""" + sync: int + """Default value: `3`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + announce: int | UndefinedType = Undefined, + delay_resp: int | UndefinedType = Undefined, + follow_up: int | UndefinedType = Undefined, + sync: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceIds. + + + Subclass of AvdModel. + + Args: + enabled: enabled + announce: announce + delay_resp: delay_resp + follow_up: follow_up + sync: sync + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "intervals": {"type": Intervals}, + "sequence_ids": {"type": SequenceIds}, + "_custom_data": {"type": dict}, + } + intervals: Intervals + """Subclass of AvdModel.""" + sequence_ids: SequenceIds + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + intervals: Intervals | UndefinedType = Undefined, + sequence_ids: SequenceIds | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingMessage. + + + Subclass of AvdModel. + + Args: + intervals: Subclass of AvdModel. + sequence_ids: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "threshold": {"type": Threshold}, + "missing_message": {"type": MissingMessage}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + threshold: Threshold + """Subclass of AvdModel.""" + missing_message: MissingMessage + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + threshold: Threshold | UndefinedType = Undefined, + missing_message: MissingMessage | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Monitor. + + + Subclass of AvdModel. + + Args: + enabled: enabled + threshold: Subclass of AvdModel. + missing_message: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "profile": {"type": str}, + "mlag": {"type": bool, "default": False}, + "domain": {"type": int, "default": 127}, + "priority1": {"type": int}, + "priority2": {"type": int}, + "auto_clock_identity": {"type": bool}, + "clock_identity_prefix": {"type": str, "default": "00:1C:73"}, + "clock_identity": {"type": str}, + "source_ip": {"type": str}, + "mode": {"type": str, "default": "boundary"}, + "mode_one_step": {"type": bool, "default": False}, + "ttl": {"type": int}, + "forward_unicast": {"type": bool, "default": False}, + "dscp": {"type": Dscp}, + "monitor": {"type": Monitor}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + profile: str | None + """ + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + """ + mlag: bool + """ + Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be + configured on the MLAG peer-link port-channel. + + Default value: `False` + """ + domain: int + """Default value: `127`""" + priority1: int | None + """default -> automatically set based on node_type.""" + priority2: int | None + """default -> (node_id modulus 256).""" + auto_clock_identity: bool | None + """ + If you prefer to have PTP clock identity be the system MAC-address of the switch, which is the + default EOS behaviour, simply disable the automatic PTP clock identity. + default -> + (clock_identity_prefix = 00:1C:73 (default)) + (PTP priority 1 as HEX) + ":00:" + (PTP priority 2 as + HEX). + """ + clock_identity_prefix: str + """ + PTP clock idetentiy 3-byte prefix. i.e. "01:02:03". + By default the 3-byte prefix is "00:1C:73". + This + can be overridden if auto_clock_identity is set to true (which is the default). + + Default value: `"00:1C:73"` + """ + clock_identity: str | None + """Set PTP clock identity manually. 6-byte value i.e. "01:02:03:04:05:06".""" + source_ip: str | None + """ + By default in EOS, PTP packets are sourced with an IP address from the routed port or from the + relevant SVI, which is the recommended behaviour. + This can be set manually if required, for example, + to a value of "10.1.2.3". + """ + mode: Literal["boundary"] + """Default value: `"boundary"`""" + mode_one_step: bool + """Default value: `False`""" + ttl: int | None + forward_unicast: bool + """ + Enable PTP unicast forwarding. + + Default value: `False` + """ + dscp: Dscp + """Subclass of AvdModel.""" + monitor: Monitor + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + profile: str | None | UndefinedType = Undefined, + mlag: bool | UndefinedType = Undefined, + domain: int | UndefinedType = Undefined, + priority1: int | None | UndefinedType = Undefined, + priority2: int | None | UndefinedType = Undefined, + auto_clock_identity: bool | None | UndefinedType = Undefined, + clock_identity_prefix: str | UndefinedType = Undefined, + clock_identity: str | None | UndefinedType = Undefined, + source_ip: str | None | UndefinedType = Undefined, + mode: Literal["boundary"] | UndefinedType = Undefined, + mode_one_step: bool | UndefinedType = Undefined, + ttl: int | None | UndefinedType = Undefined, + forward_unicast: bool | UndefinedType = Undefined, + dscp: Dscp | UndefinedType = Undefined, + monitor: Monitor | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ptp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + profile: + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + mlag: + Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be + configured on the MLAG peer-link port-channel. + domain: domain + priority1: default -> automatically set based on node_type. + priority2: default -> (node_id modulus 256). + auto_clock_identity: + If you prefer to have PTP clock identity be the system MAC-address of the switch, which is the + default EOS behaviour, simply disable the automatic PTP clock identity. + default -> + (clock_identity_prefix = 00:1C:73 (default)) + (PTP priority 1 as HEX) + ":00:" + (PTP priority 2 as + HEX). + clock_identity_prefix: + PTP clock idetentiy 3-byte prefix. i.e. "01:02:03". + By default the 3-byte prefix is "00:1C:73". + This + can be overridden if auto_clock_identity is set to true (which is the default). + clock_identity: Set PTP clock identity manually. 6-byte value i.e. "01:02:03:04:05:06". + source_ip: + By default in EOS, PTP packets are sourced with an IP address from the routed port or from the + relevant SVI, which is the recommended behaviour. + This can be set manually if required, for example, + to a value of "10.1.2.3". + mode: mode + mode_one_step: mode_one_step + ttl: ttl + forward_unicast: Enable PTP unicast forwarding. + dscp: Subclass of AvdModel. + monitor: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class WanHa(AvdModel): + """Subclass of AvdModel.""" + + class HaInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + HaInterfaces._item_type = str + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "ipsec": {"type": bool, "default": True}, + "mtu": {"type": int, "default": 9194}, + "ha_interfaces": {"type": HaInterfaces}, + "ha_ipv4_pool": {"type": str}, + "max_ha_interfaces": {"type": int}, + "port_channel_id": {"type": int}, + "use_port_channel_for_direct_ha": {"type": bool, "default": True}, + "flow_tracking": {"type": FlowTracking}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group.""" + ipsec: bool + """ + Enable / Disable IPsec over HA path-group when HA is enabled. + + Default value: `True` + """ + mtu: int + """ + Set MTU on WAN HA interfaces. + + Default value: `9194` + """ + ha_interfaces: HaInterfaces + """ + Local WAN HA interfaces + Overwrite the default behavior which is to pick all the `uplink_interfaces`. + Can be used to filter uplink interfaces when there are multiple uplinks. + Limitations: + Either all + interfaces must be uplinks or all interfaces must not be uplinks. + Only one interface is supported + for non uplinks. + + Subclass of AvdList with `str` items. + """ + ha_ipv4_pool: str | None + """ + IP address pool used for WAN HA connectivity. + IP is derived from the node ID. + Not used for uplink + interfaces. + """ + max_ha_interfaces: int | None + """ + Number of parallel links towards HA switches. + Can be used to reserve IP addresses for future + parallel HA links. + """ + port_channel_id: int | None + """Port-channel ID to use for direct HA.""" + use_port_channel_for_direct_ha: bool + """ + Enable or disable using a port-channel interface for direct HA when there is only one interface. + This feature was introduced in EOS 4.33.0F. + + Default value: `True` + """ + flow_tracking: FlowTracking + """ + Configures flow-tracking on the HA interfaces. Overrides `fabric_flow_tracking.wan_ha_links` + setting. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + ipsec: bool | UndefinedType = Undefined, + mtu: int | UndefinedType = Undefined, + ha_interfaces: HaInterfaces | UndefinedType = Undefined, + ha_ipv4_pool: str | None | UndefinedType = Undefined, + max_ha_interfaces: int | None | UndefinedType = Undefined, + port_channel_id: int | None | UndefinedType = Undefined, + use_port_channel_for_direct_ha: bool | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + WanHa. + + + Subclass of AvdModel. + + Args: + enabled: Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group. + ipsec: Enable / Disable IPsec over HA path-group when HA is enabled. + mtu: Set MTU on WAN HA interfaces. + ha_interfaces: + Local WAN HA interfaces + Overwrite the default behavior which is to pick all the `uplink_interfaces`. + Can be used to filter uplink interfaces when there are multiple uplinks. + Limitations: + Either all + interfaces must be uplinks or all interfaces must not be uplinks. + Only one interface is supported + for non uplinks. + + Subclass of AvdList with `str` items. + ha_ipv4_pool: + IP address pool used for WAN HA connectivity. + IP is derived from the node ID. + Not used for uplink + interfaces. + max_ha_interfaces: + Number of parallel links towards HA switches. + Can be used to reserve IP addresses for future + parallel HA links. + port_channel_id: Port-channel ID to use for direct HA. + use_port_channel_for_direct_ha: + Enable or disable using a port-channel interface for direct HA when there is only one interface. + This feature was introduced in EOS 4.33.0F. + flow_tracking: + Configures flow-tracking on the HA interfaces. Overrides `fabric_flow_tracking.wan_ha_links` + setting. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L3InterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "peer_as": {"type": str}, + "ipv4_prefix_list_in": {"type": str}, + "ipv4_prefix_list_out": {"type": str}, + "_custom_data": {"type": dict}, + } + peer_as: str + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + ipv4_prefix_list_in: str | None + """ + Prefix List Name. Accept routes for only these prefixes from the peer. + Required for wan interfaces. + """ + ipv4_prefix_list_out: str | None + """ + Prefix List Name. Advertise routes for only these prefixes. + If not specified, nothing would be + advertised. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + peer_as: str | UndefinedType = Undefined, + ipv4_prefix_list_in: str | None | UndefinedType = Undefined, + ipv4_prefix_list_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + peer_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + ipv4_prefix_list_in: + Prefix List Name. Accept routes for only these prefixes from the peer. + Required for wan interfaces. + ipv4_prefix_list_out: + Prefix List Name. Advertise routes for only these prefixes. + If not specified, nothing would be + advertised. + _custom_data: _custom_data + + """ + + class StaticRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "_custom_data": {"type": dict}} + prefix: str + """IPv4_network/Mask.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, prefix: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + StaticRoutesItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv4_network/Mask. + _custom_data: _custom_data + + """ + + class StaticRoutes(AvdList[StaticRoutesItem]): + """Subclass of AvdList with `StaticRoutesItem` items.""" + + StaticRoutes._item_type = StaticRoutesItem + + class CvPathfinderInternetExit(AvdModel): + """Subclass of AvdModel.""" + + class PoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "tunnel_interface_numbers": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Internet-exit policy name.""" + tunnel_interface_numbers: str | None + """ + Number range to use for Tunnel interfaces to an internet-exit service provider using this local + interface. + Examples: '1-3' or '100,200,300' + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + tunnel_interface_numbers: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PoliciesItem. + + + Subclass of AvdModel. + + Args: + name: Internet-exit policy name. + tunnel_interface_numbers: + Number range to use for Tunnel interfaces to an internet-exit service provider using this local + interface. + Examples: '1-3' or '100,200,300' + _custom_data: _custom_data + + """ + + class Policies(AvdIndexedList[str, PoliciesItem]): + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Policies._item_type = PoliciesItem + + _fields: ClassVar[dict] = {"policies": {"type": Policies}, "_custom_data": {"type": dict}} + policies: Policies + """ + List of Internet-exit policies using this interface as exit. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, policies: Policies | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + CvPathfinderInternetExit. + + + Subclass of AvdModel. + + Args: + policies: + List of Internet-exit policies using this interface as exit. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "profile": {"type": str}, + "name": {"type": str}, + "description": {"type": str}, + "ip_address": {"type": str}, + "dhcp_ip": {"type": str}, + "public_ip": {"type": str}, + "encapsulation_dot1q_vlan": {"type": int}, + "dhcp_accept_default_route": {"type": bool, "default": True}, + "enabled": {"type": bool, "default": True}, + "speed": {"type": str}, + "peer": {"type": str}, + "peer_interface": {"type": str}, + "peer_ip": {"type": str}, + "bgp": {"type": Bgp}, + "ipv4_acl_in": {"type": str}, + "ipv4_acl_out": {"type": str}, + "static_routes": {"type": StaticRoutes}, + "qos_profile": {"type": str}, + "wan_carrier": {"type": str}, + "wan_circuit_id": {"type": str}, + "connected_to_pathfinder": {"type": bool, "default": True}, + "cv_pathfinder_internet_exit": {"type": CvPathfinderInternetExit}, + "raw_eos_cli": {"type": str}, + "flow_tracking": {"type": FlowTracking}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + profile: str | None + """L3 interface profile name. Profile defined under `l3_interface_profiles`.""" + name: str + """ + Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. + For a + subinterface, the parent physical interface is automatically created. + """ + description: str | None + """ + Interface description. + If not set a default description will be configured with '[[ + ]]'. + """ + ip_address: str | None + """Node IPv4 address/Mask or 'dhcp'.""" + dhcp_ip: str | None + """ + When the `ip_address` is `dhcp`, this optional field allows to indicate the expected + IPv4 address + (without mask) to be allocated on the interface if known. + This is not rendered in the configuration + but can be used for substitution of 'interface_ip' in the Access-list + set under `ipv4_acl_in` and + `ipv4_acl_out`. + """ + public_ip: str | None + """ + Node IPv4 address (no mask). + + This is used to get the public IP (if known) when the device is behind + NAT. + This is only used for `wan_rr` routers (AutoVPN RRs and Pathfinders) to determine the Public IP + with the following preference: + `wan_route_servers.path_groups.interfaces.ip_address` + -> + `l3_interfaces.public_ip` + -> `l3_interfaces.ip_address` + + The determined Public IP is used + by WAN routers when peering with this interface. + """ + encapsulation_dot1q_vlan: int | None + """ + For subinterfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + """ + dhcp_accept_default_route: bool + """ + Accept a default route from DHCP if `ip_address` is set to `dhcp`. + + Default value: `True` + """ + enabled: bool + """ + Enable or Shutdown the interface. + + Default value: `True` + """ + speed: str | None + """ + Speed should be set in the format `` or `forced ` or `auto + `. + """ + peer: str | None + """The peer device name. Used for description and documentation.""" + peer_interface: str | None + """The peer device interface. Used for description and documentation.""" + peer_ip: str | None + """ + The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true + and `ip` is an IP address. + """ + bgp: Bgp + """ + Enforce IPv4 BGP peering for the peer + + Subclass of AvdModel. + """ + ipv4_acl_in: str | None + """ + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + Required + for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under + `wan_carriers`. + """ + ipv4_acl_out: str | None + """ + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + """ + static_routes: StaticRoutes + """ + Configure IPv4 static routes pointing to `peer_ip`. + + Subclass of AvdList with `StaticRoutesItem` + items. + """ + qos_profile: str | None + """QOS service profile.""" + wan_carrier: str | None + """ + The WAN carrier this interface is connected to. + This is used to infer the path-groups in which this + interface should be configured. + Unless the carrier is marked as 'trusted' under `wan_carriers`, + `ipv4_acl_in` is also required on all WAN interfaces. + """ + wan_circuit_id: str | None + """ + The WAN circuit ID for this interface. + This is not rendered in the configuration but used for WAN + designs. + """ + connected_to_pathfinder: bool + """ + For a WAN interface (`wan_carrier` is set), allow to disable the static tunnel towards Pathfinders. + + Default value: `True` + """ + cv_pathfinder_internet_exit: CvPathfinderInternetExit + """ + PREVIEW: This key is in preview mode + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the interface in the final EOS configuration.""" + flow_tracking: FlowTracking + """ + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + """ + structured_config: StructuredConfig + """ + Custom structured config for the Ethernet interface. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | None | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + dhcp_ip: str | None | UndefinedType = Undefined, + public_ip: str | None | UndefinedType = Undefined, + encapsulation_dot1q_vlan: int | None | UndefinedType = Undefined, + dhcp_accept_default_route: bool | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + speed: str | None | UndefinedType = Undefined, + peer: str | None | UndefinedType = Undefined, + peer_interface: str | None | UndefinedType = Undefined, + peer_ip: str | None | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + ipv4_acl_in: str | None | UndefinedType = Undefined, + ipv4_acl_out: str | None | UndefinedType = Undefined, + static_routes: StaticRoutes | UndefinedType = Undefined, + qos_profile: str | None | UndefinedType = Undefined, + wan_carrier: str | None | UndefinedType = Undefined, + wan_circuit_id: str | None | UndefinedType = Undefined, + connected_to_pathfinder: bool | UndefinedType = Undefined, + cv_pathfinder_internet_exit: CvPathfinderInternetExit | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L3InterfacesItem. + + + Subclass of AvdModel. + + Args: + profile: L3 interface profile name. Profile defined under `l3_interface_profiles`. + name: + Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. + For a + subinterface, the parent physical interface is automatically created. + description: + Interface description. + If not set a default description will be configured with '[[ + ]]'. + ip_address: Node IPv4 address/Mask or 'dhcp'. + dhcp_ip: + When the `ip_address` is `dhcp`, this optional field allows to indicate the expected + IPv4 address + (without mask) to be allocated on the interface if known. + This is not rendered in the configuration + but can be used for substitution of 'interface_ip' in the Access-list + set under `ipv4_acl_in` and + `ipv4_acl_out`. + public_ip: + Node IPv4 address (no mask). + + This is used to get the public IP (if known) when the device is behind + NAT. + This is only used for `wan_rr` routers (AutoVPN RRs and Pathfinders) to determine the Public IP + with the following preference: + `wan_route_servers.path_groups.interfaces.ip_address` + -> + `l3_interfaces.public_ip` + -> `l3_interfaces.ip_address` + + The determined Public IP is used + by WAN routers when peering with this interface. + encapsulation_dot1q_vlan: + For subinterfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + dhcp_accept_default_route: Accept a default route from DHCP if `ip_address` is set to `dhcp`. + enabled: Enable or Shutdown the interface. + speed: + Speed should be set in the format `` or `forced ` or `auto + `. + peer: The peer device name. Used for description and documentation. + peer_interface: The peer device interface. Used for description and documentation. + peer_ip: + The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true + and `ip` is an IP address. + bgp: + Enforce IPv4 BGP peering for the peer + + Subclass of AvdModel. + ipv4_acl_in: + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + Required + for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under + `wan_carriers`. + ipv4_acl_out: + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + static_routes: + Configure IPv4 static routes pointing to `peer_ip`. + + Subclass of AvdList with `StaticRoutesItem` + items. + qos_profile: QOS service profile. + wan_carrier: + The WAN carrier this interface is connected to. + This is used to infer the path-groups in which this + interface should be configured. + Unless the carrier is marked as 'trusted' under `wan_carriers`, + `ipv4_acl_in` is also required on all WAN interfaces. + wan_circuit_id: + The WAN circuit ID for this interface. + This is not rendered in the configuration but used for WAN + designs. + connected_to_pathfinder: For a WAN interface (`wan_carrier` is set), allow to disable the static tunnel towards Pathfinders. + cv_pathfinder_internet_exit: + PREVIEW: This key is in preview mode + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the interface in the final EOS configuration. + flow_tracking: + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + structured_config: + Custom structured config for the Ethernet interface. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): + """Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + L3Interfaces._item_type = L3InterfacesItem + + _fields: ClassVar[dict] = { + "group": {"type": str}, + "nodes": {"type": Nodes}, + "id": {"type": int}, + "platform": {"type": str}, + "mac_address": {"type": str}, + "system_mac_address": {"type": str}, + "serial_number": {"type": str}, + "rack": {"type": str}, + "mgmt_ip": {"type": str}, + "mgmt_gateway": {"type": str}, + "ipv6_mgmt_ip": {"type": str}, + "ipv6_mgmt_gateway": {"type": str}, + "mgmt_interface": {"type": str}, + "link_tracking": {"type": LinkTracking}, + "lacp_port_id_range": {"type": LacpPortIdRange}, + "always_configure_ip_routing": {"type": bool, "default": False}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "uplink_type": {"type": str}, + "uplink_ipv4_pool": {"type": str}, + "uplink_interfaces": {"type": UplinkInterfaces}, + "uplink_switch_interfaces": {"type": UplinkSwitchInterfaces}, + "uplink_switches": {"type": UplinkSwitches}, + "uplink_interface_speed": {"type": str}, + "uplink_switch_interface_speed": {"type": str}, + "uplink_mtu": {"type": int}, + "max_uplink_switches": {"type": int}, + "max_parallel_uplinks": {"type": int, "default": 1}, + "uplink_bfd": {"type": bool, "default": False}, + "uplink_native_vlan": {"type": int}, + "uplink_ptp": {"type": UplinkPtp}, + "uplink_macsec": {"type": UplinkMacsec}, + "uplink_port_channel_id": {"type": int}, + "uplink_switch_port_channel_id": {"type": int}, + "uplink_structured_config": {"type": dict}, + "mlag_port_channel_structured_config": {"type": MlagPortChannelStructuredConfig}, + "mlag_peer_vlan_structured_config": {"type": MlagPeerVlanStructuredConfig}, + "mlag_peer_l3_vlan_structured_config": {"type": MlagPeerL3VlanStructuredConfig}, + "short_esi": {"type": str}, + "isis_system_id_prefix": {"type": str}, + "isis_maximum_paths": {"type": int}, + "is_type": {"type": str}, + "node_sid_base": {"type": int, "default": 0}, + "loopback_ipv4_pool": {"type": str}, + "loopback_ipv4_address": {"type": str}, + "vtep_loopback_ipv4_pool": {"type": str}, + "vtep_loopback_ipv4_address": {"type": str}, + "loopback_ipv4_offset": {"type": int, "default": 0}, + "loopback_ipv6_pool": {"type": str}, + "loopback_ipv6_offset": {"type": int, "default": 0}, + "vtep": {"type": bool}, + "vtep_loopback": {"type": str}, + "bgp_as": {"type": str}, + "bgp_defaults": {"type": BgpDefaults}, + "evpn_role": {"type": str}, + "evpn_route_servers": {"type": EvpnRouteServers}, + "evpn_services_l2_only": {"type": bool, "default": False}, + "filter": {"type": Filter}, + "igmp_snooping_enabled": {"type": bool}, + "evpn_gateway": {"type": EvpnGateway}, + "ipvpn_gateway": {"type": IpvpnGateway}, + "mlag": {"type": bool, "default": True}, + "mlag_dual_primary_detection": {"type": bool, "default": False}, + "mlag_ibgp_origin_incomplete": {"type": bool, "default": True}, + "mlag_interfaces": {"type": MlagInterfaces}, + "mlag_interfaces_speed": {"type": str}, + "mlag_peer_l3_vlan": {"type": int, "default": 4093}, + "mlag_peer_l3_ipv4_pool": {"type": str}, + "mlag_peer_vlan": {"type": int, "default": 4094}, + "mlag_peer_link_allowed_vlans": {"type": str}, + "mlag_peer_address_family": {"type": str, "default": "ipv4"}, + "mlag_peer_ipv4_pool": {"type": str}, + "mlag_peer_ipv6_pool": {"type": str}, + "mlag_port_channel_id": {"type": int}, + "mlag_domain_id": {"type": str}, + "spanning_tree_mode": {"type": str}, + "spanning_tree_priority": {"type": int, "default": 32768}, + "spanning_tree_root_super": {"type": bool, "default": False}, + "virtual_router_mac_address": {"type": str}, + "inband_mgmt_interface": {"type": str}, + "inband_mgmt_vlan": {"type": int, "default": 4092}, + "inband_mgmt_subnet": {"type": str}, + "inband_mgmt_ip": {"type": str}, + "inband_mgmt_gateway": {"type": str}, + "inband_mgmt_ipv6_address": {"type": str}, + "inband_mgmt_ipv6_subnet": {"type": str}, + "inband_mgmt_ipv6_gateway": {"type": str}, + "inband_mgmt_description": {"type": str, "default": "Inband Management"}, + "inband_mgmt_vlan_name": {"type": str, "default": "INBAND_MGMT"}, + "inband_mgmt_vrf": {"type": str, "default": "default"}, + "inband_mgmt_mtu": {"type": int, "default": 1500}, + "inband_ztp": {"type": bool, "default": False}, + "inband_ztp_lacp_fallback_delay": {"type": int, "default": 30}, + "mpls_overlay_role": {"type": str}, + "overlay_address_families": {"type": OverlayAddressFamilies}, + "mpls_route_reflectors": {"type": MplsRouteReflectors}, + "bgp_cluster_id": {"type": str}, + "ptp": {"type": Ptp}, + "wan_role": {"type": str}, + "cv_pathfinder_transit_mode": {"type": str}, + "cv_pathfinder_region": {"type": str}, + "cv_pathfinder_site": {"type": str}, + "wan_ha": {"type": WanHa}, + "dps_mss_ipv4": {"type": str, "default": "auto"}, + "l3_interfaces": {"type": L3Interfaces}, + "data_plane_cpu_allocation_max": {"type": int}, + "flow_tracker_type": {"type": str}, + "_custom_data": {"type": dict}, + } + group: str + """ + The Node Group Name is used for MLAG domain unless set with 'mlag_domain_id'. + The Node Group Name is + also used for peer description on downstream switches' uplinks. + """ + nodes: Nodes + """ + Define variables per node. + + Subclass of AvdIndexedList with `NodesItem` items. Primary key is `name` + (`str`). + """ + id: int | None + """Unique identifier used for IP addressing and other algorithms.""" + platform: str | None + """Arista platform family.""" + mac_address: str | None + """Leverage to document management interface mac address.""" + system_mac_address: str | None + """ + System MAC Address in this following format: "xx:xx:xx:xx:xx:xx". + Set to the same MAC address as + available in "show version" on the device. + "system_mac_address" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + """ + serial_number: str | None + """ + Set to the Serial Number of the device. + Only used for documentation purpose in the fabric + documentation and part of the structured_config. + "serial_number" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + """ + rack: str | None + """Rack that the switch is located in (only used in snmp_settings location).""" + mgmt_ip: str | None + """Node management interface IPv4 address.""" + mgmt_gateway: str | None + """ + This key sets the management gateway for the device. It takes precedence over the global + `mgmt_gateway`. + """ + ipv6_mgmt_ip: str | None + """Node management interface IPv6 address.""" + ipv6_mgmt_gateway: str | None + """ + This key sets the ipv6 management gateway for the device. It takes precedence over the global + `ipv6_mgmt_gateway`. + """ + mgmt_interface: str | None + """ + Management Interface Name. + Default -> platform_management_interface -> mgmt_interface -> + "Management1". + """ + link_tracking: LinkTracking + """ + This configures the Link Tracking Group on a switch as well as adds the p2p-uplinks of the switch as + the upstream interfaces. + Useful in EVPN multhoming designs. + + + Subclass of AvdModel. + """ + lacp_port_id_range: LacpPortIdRange + """ + This will generate the "lacp port-id range", "begin" and "end" values based on node "id" and the + number of nodes in the "node_group". + Unique LACP port-id ranges are recommended for EVPN Multihoming + designs. + + + Subclass of AvdModel. + """ + always_configure_ip_routing: bool + """ + Force configuration of "ip routing" even on L2 devices. + Use this to retain behavior of AVD versions + below 4.0.0. + + Default value: `False` + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the root level of the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + """ + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None + """ + Override the default `uplink_type` set at the `node_type_key` level. + `uplink_type` must be "p2p" if + `vtep` or `underlay_router` is true for the `node_type_key` definition. + """ + uplink_ipv4_pool: str | None + """IPv4 subnet to use to connect to uplink switches.""" + uplink_interfaces: UplinkInterfaces + """ + Local uplink interfaces. + Each list item supports range syntax that can be expanded into a list of + interfaces. + If uplink_interfaces is not defined, platform-specific defaults (defined under + default_interfaces) will be used instead. + Please note that default_interfaces are not defined by + default, you should define these yourself. + + + Subclass of AvdList with `str` items. + """ + uplink_switch_interfaces: UplinkSwitchInterfaces + """ + Interfaces located on uplink switches. + + Subclass of AvdList with `str` items. + """ + uplink_switches: UplinkSwitches + """Subclass of AvdList with `str` items.""" + uplink_interface_speed: str | None + """ + Set point-to-Point interface speed and will apply to uplink interfaces on both ends. + (Uplink switch + interface speed can be overridden with `uplink_switch_interface_speed`). + Speed should be set in the + format `` or `forced ` or `auto `. + """ + uplink_switch_interface_speed: str | None + """ + 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: int | None + """Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting.""" + max_uplink_switches: int | None + """ + 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: 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 + """ + Enable bfd on uplink interfaces. + + Default value: `False` + """ + uplink_native_vlan: int | None + """ + 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: UplinkPtp + """ + Enable PTP on all infrastructure links. + + Subclass of AvdModel. + """ + uplink_macsec: UplinkMacsec + """ + Enable MacSec on all uplinks. + + Subclass of AvdModel. + """ + uplink_port_channel_id: int | None + """ + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink Port-channel + ID will be set to the number of the lowest member interface defined under `uplink_interfaces`. + For + example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ Eth11/1, Eth22/1 ] -> ID 111 + For + MLAG port-channels ID will be based on the lowest member interface on the first MLAG switch. + This + option overrides the default behavior and statically sets the local Port-channel ID. + Note! Make sure + the ID is unique and does not overlap with autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between 1 and 2000 and both MLAG switches must have the same + value. + """ + uplink_switch_port_channel_id: int | None + """ + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink switch Port- + channel ID will be set to the number of the first interface defined under + `uplink_switch_interfaces`. + For example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ + Eth11/1, Eth22/1 ] -> ID 111 + For MLAG port-channels ID will be based on the lowest member interface + on the first MLAG switch. + This option overrides the default behavior and statically sets the Port- + channel ID on the uplink switch. + Note! Make sure the ID is unique and does not overlap with + autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between + 1 and 2000 and both MLAG switches must have the same value. + """ + uplink_structured_config: dict + """ + Custom structured config applied to "uplink_interfaces", and "uplink_switch_interfaces". + When + uplink_type == "p2p", custom structured config added under ethernet_interfaces.[name=] + for eos_cli_config_gen overrides the settings on the ethernet interface level. + When uplink_type == + "port-channel", custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen overrides the settings on the port-channel interface level. + "uplink_structured_config" is applied after "structured_config", so it can override + "structured_config" defined on node-level. + Note! The content of this dictionary is _not_ validated + by the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + """ + mlag_port_channel_structured_config: MlagPortChannelStructuredConfig + """ + Custom structured config applied to MLAG peer link port-channel id. + Added under + port_channel_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the + port-channel interface level. + "mlag_port_channel_structured_config" is applied after + "structured_config", so it can override "structured_config" defined on node-level. + + + Subclass of + AvdModel. + """ + mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig + """ + Custom structured config applied to MLAG Peer Link (control link) SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_vlan_structured_config" is applied after "structured_config", so it can + override "structured_config" defined on node-level. + + + Subclass of AvdModel. + """ + mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig + """ + Custom structured config applied to MLAG underlay L3 peering SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_l3_vlan_structured_config" is applied after "structured_config", so it + can override "structured_config" defined on node-level. + + + Subclass of AvdModel. + """ + short_esi: str | None + """ + short_esi only valid for l2leaf devices using port-channel uplink. + Setting short_esi to "auto" + generates the short_esi automatically using a hash of configuration elements. + < 0000:0000:0000 | + auto >. + """ + isis_system_id_prefix: str | None + """(4.4 hexadecimal).""" + isis_maximum_paths: int | None + """Number of path to configure in ECMP for ISIS.""" + is_type: Literal["level-1-2", "level-1", "level-2"] | None + """Overrides `isis_default_is_type`.""" + node_sid_base: int + """ + Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID. + + Default value: `0` + """ + loopback_ipv4_pool: str | None + """IPv4 subnet for Loopback0 allocation.""" + loopback_ipv4_address: str | None + """ + IPv4 address without mask for Loopback0. + When set, it takes precedence over `loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not catch duplicates. + """ + vtep_loopback_ipv4_pool: str | None + """IPv4 subnet for VTEP-Loopback allocation.""" + vtep_loopback_ipv4_address: str | None + """ + IPv4 address without mask for VTEP-Loopback. + When set, it takes precedence over + `vtep_loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not + catch duplicates. + """ + loopback_ipv4_offset: int + """ + Offset all assigned loopback IP addresses. + Required when the < loopback_ipv4_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid over-lapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv4_offset: < total # spine switches > or vice versa. + + Default value: `0` + """ + loopback_ipv6_pool: str | None + """IPv6 subnet for Loopback0 allocation.""" + loopback_ipv6_offset: int + """ + Offset all assigned loopback IPv6 addresses. + Required when the < loopback_ipv6_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid overlapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv6_offset: < total # spine switches > or vice versa. + + Default value: `0` + """ + vtep: bool | None + """ + Node is configured as a VTEP when applicable based on 'overlay_routing_protocol'. + Overrides VTEP + setting inherited from node_type_keys. + """ + vtep_loopback: str | None + """Set VXLAN source interface.""" + bgp_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + Required with eBGP. + """ + bgp_defaults: BgpDefaults + """ + List of EOS commands to apply to BGP daemon. + + Subclass of AvdList with `str` items. + """ + evpn_role: Literal["client", "server", "none"] | None + """ + Acting role in EVPN control plane. + Default is set in node_type definition from node_type_keys. + """ + evpn_route_servers: EvpnRouteServers + """ + List of nodes acting as EVPN Route-Servers / Route-Reflectors. + + Subclass of AvdList with `str` + items. + """ + evpn_services_l2_only: bool + """ + Possibility to prevent configuration of Tenant VRFs and SVIs. + Override node definition + "network_services_l3" from node_type_keys. + This allows support for centralized routing. + + Default value: `False` + """ + filter: Filter + """ + Filter L3 and L2 network services based on tenant and tags (and operation filter). + If filter is not + defined it will default to all. + + + Subclass of AvdModel. + """ + igmp_snooping_enabled: bool | None + """Activate or deactivate IGMP snooping on device level.""" + evpn_gateway: EvpnGateway + """ + Node is acting as EVPN Multi-Domain Gateway. + New BGP peer-group is generated between EVPN GWs in + different domains or between GWs and Route Servers. + Name can be changed under + "bgp_peer_groups.evpn_overlay_core" variable. + L3 rechability for different EVPN GWs must be already + in place, it is recommended to use DCI & L3 Edge if Route Servers and GWs are not defined under the + same Ansible inventory. + + + Subclass of AvdModel. + """ + ipvpn_gateway: IpvpnGateway + """ + Node is acting as IP-VPN Gateway for EVPN to MPLS-IP-VPN Interworking. The BGP peer group used for + this is "bgp_peer_groups.ipvpn_gateway_peers". + L3 Reachability is required for this to work, the + preferred method to establish underlay connectivity is to use core_interfaces. + + + Subclass of + AvdModel. + """ + mlag: bool + """ + Enable / Disable auto MLAG, when two nodes are defined in node group. + + Default value: `True` + """ + mlag_dual_primary_detection: bool + """ + Enable / Disable MLAG dual primary detection. + + Default value: `False` + """ + mlag_ibgp_origin_incomplete: bool + """ + Set origin of routes received from MLAG iBGP peer to incomplete. + The purpose is to optimize routing + for leaf loopbacks from spine perspective and + avoid suboptimal routing via peerlink for control + plane traffic. + + Default value: `True` + """ + mlag_interfaces: MlagInterfaces + """ + Each list item supports range syntax that can be expanded into a list of interfaces. + Required when + MLAG leafs are present in the topology. + + + Subclass of AvdList with `str` items. + """ + mlag_interfaces_speed: str | None + """ + Set MLAG interface speed. + Speed should be set in the format `` or `forced + ` or `auto `. + """ + mlag_peer_l3_vlan: int + """ + Underlay L3 peering SVI interface id. + If set to 0 or the same vlan as mlag_peer_vlan, the + mlag_peer_vlan will be used for L3 peering. + + Default value: `4093` + """ + mlag_peer_l3_ipv4_pool: str | None + """ + IP address pool used for MLAG underlay L3 peering. IP is derived from the node id. + Required when + MLAG leafs present in topology and they are using a separate L3 peering VLAN. + """ + mlag_peer_vlan: int + """ + MLAG Peer Link (control link) SVI interface id. + + Default value: `4094` + """ + mlag_peer_link_allowed_vlans: str | None + mlag_peer_address_family: Literal["ipv4", "ipv6"] + """ + IP address family used to establish MLAG Peer Link (control link). + `ipv6` requires EOS version + 4.31.1F or higher. + Note: `ipv6` is not supported in combination with a common MLAG peer link VLAN + (ex. `mlag_peer_l3_vlan` set to 4094). + + Default value: `"ipv4"` + """ + mlag_peer_ipv4_pool: str | None + """ + IPv4 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv4` (default). + """ + mlag_peer_ipv6_pool: str | None + """ + IPv6 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv6`. + """ + mlag_port_channel_id: int | None + """ + If not set, the mlag port-channel id is generated based on the digits of the first interface present + in 'mlag_interfaces'. + Valid port-channel id numbers are < 1-2000 > for EOS < 4.25.0F and < 1 - + 999999 > for EOS >= 4.25.0F. + """ + mlag_domain_id: str | None + """MLAG Domain ID. If not set the node group name (Set with "group" key) will be used.""" + spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None + spanning_tree_priority: int + """ + Spanning-tree priority configured for the selected mode. + For `rapid-pvst` the priority can also be + set per VLAN under network services. + + Default value: `32768` + """ + spanning_tree_root_super: bool + """Default value: `False`""" + virtual_router_mac_address: str | None + """Virtual router mac address for anycast gateway.""" + inband_mgmt_interface: str | None + """ + Pointer to interface used for inband management. + All configuration must be done using other data + models like network services or structured_config. + 'inband_mgmt_interface' is only used to refer to + this interface as source in various management protocol settings (future feature). + + On L2 switches, + this defaults to Vlan if either 'inband_mgmt_subnet' or 'inband_mgmt_ip' is set. + """ + inband_mgmt_vlan: int + """ + VLAN number used for inband management on L2 switches (switches using port-channel trunks as + uplinks). + When using 'inband_mgmt_subnet' the VLAN and SVIs will be created automatically on this + switch as well as all 'uplink_switches'. + When using 'inband_mgmt_ip' the VLAN and SVI will only be + created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be + created using network services data models. + + Default value: `4092` + """ + inband_mgmt_subnet: str | None + """ + Optional IP subnet assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ip virtual-router" and host-route injection based on + ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + + 3 + + GW on l2leafs : + 1 + Assign range larger than total l2leafs + 5 + Setting is ignored if 'inband_mgmt_ip' is set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + """ + inband_mgmt_ip: str | None + """ + IP address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_subnet', hence all behavior of 'inband_mgmt_subnet' is removed. + + If this is set the + VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN and SVI on + the parent switches must be created using network services data models. + + This setting is applicable + to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_gateway: str | None + """ + Default gateway configured in the 'inband_mgmt_vrf' when using 'inband_mgmt_ip'. Otherwise gateway + is derived from 'inband_mgmt_subnet' if set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_address: str | None + """ + IPv6 address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_ipv6_subnet', hence the configuration of 'inband_mgmt_ipv6_subnet' is ignored. + + If this + is set the VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN + and SVI on the parent switches must be created using network services data models. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_subnet: str | None + """ + Optional IPv6 prefix assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ipv6 virtual-router" and host-route injection based + on ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN + extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + 3 + + GW on l2leafs : + 1 + Assign range larger than + total l2leafs + 5 + + Setting is ignored if 'inband_mgmt_ipv6_address' is set. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_gateway: str | None + """ + Default gateway configured in the 'inband_mgmt_vrf'. + Used when `inband_mgmt_ipv6_address` is set. + Ignored when 'inband_mgmt_ipv6_subnet' is set (first IP in subnet used as gateway). + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_description: str + """ + Description configured on the Inband Management SVI. + + This setting is only applied on the devices + where it is set, it does not automatically affect any parent/child devices configuration, so it must + be set on each applicable node/node-group/node-type as needed. + + Default value: `"Inband Management"` + """ + inband_mgmt_vlan_name: str + """ + Name configured on the Inband Management VLAN. + This setting is only applied on the devices where it + is set, it does not automatically affect any parent/child devices configuration, so it must be set + on each applicable node/node-group/node-type as needed. + + Default value: `"INBAND_MGMT"` + """ + inband_mgmt_vrf: str + """ + VRF configured on the Inband Management Interface. + The VRF is created if not already created by + other means. + This setting is only applied on the devices where it is set, it does not automatically + affect any parent/child devices configuration, so it must be set on each applicable node/node- + group/node-type as needed. + + Default value: `"default"` + """ + inband_mgmt_mtu: int + """ + MTU configured on the Inband Management Interface. + This setting is only applied on the devices where + it is set, it does not automatically affect any parent/child devices configuration, so it must be + set on each applicable node/node-group/node-type as needed. + + Default value: `1500` + """ + inband_ztp: bool + """ + Enable to configure upstream device with proper configuration to allow downstream devices to be + Zero-Touch-Provisioned over the uplink interfaces. + For L2 devices this setting also requires that + the `inband_mgmt_vlan` is set for the node. + + PREVIEW: Support for L3 devices is marked as "preview", + meaning the data models or generated configuration can change at any time. + + Default value: `False` + """ + inband_ztp_lacp_fallback_delay: int + """ + Set the LACP fallback timeout of the upstream device's port-channel towards the downstream inband + ZTP node. + This setting also requires that `inband_ztp` is set for the node. + + Default value: `30` + """ + mpls_overlay_role: Literal["client", "server", "none"] | None + """ + Set the default mpls overlay role. + Acting role in overlay control plane. + """ + overlay_address_families: OverlayAddressFamilies + """ + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + """ + mpls_route_reflectors: MplsRouteReflectors + """ + List of inventory hostname acting as MPLS route-reflectors. + + Subclass of AvdList with `str` items. + """ + bgp_cluster_id: str | None + """Set BGP cluster id.""" + ptp: Ptp + """Subclass of AvdModel.""" + wan_role: Literal["client", "server"] | None + """ + Override the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + """ + cv_pathfinder_transit_mode: Literal["region", "zone"] | None + """ + Configure the transit mode for a WAN client for CV Pathfinder designs + only when the `wan_mode` root + key is set to `cv_pathfinder`. + + 'zone' is currently not supported. + """ + cv_pathfinder_region: str | None + """ + The CV Pathfinder region name. + This key is required for WAN routers but optional for pathfinders. + The region name must be defined under 'cv_pathfinder_regions'. + """ + cv_pathfinder_site: str | None + """ + The CV Pathfinder site name. + This key is required for WAN routers but optional for pathfinders. + For + WAN routers and pathfinders with `cv_pathfinder_region`, the site name must be defined for the + relevant region under 'cv_pathfinder_regions'. + For pathfinders without `cv_pathfinder_region` set, + the site must be defined under `cv_pathfinder_global_sites`. + """ + wan_ha: WanHa + """ + PREVIEW: This key is currently not supported + + The key is supported only if `wan_mode` == `cv- + pathfinder`. + AutoVPN support is still to be determined. + + Maximum 2 devices supported by group for + HA. + + Subclass of AvdModel. + """ + dps_mss_ipv4: str + """ + IPv4 MSS value configured under "router path-selection" on WAN Devices. + + Default value: `"auto"` + """ + l3_interfaces: L3Interfaces + """ + L3 Interfaces to configure on the node. + Used to define the node for WAN interfaces when + `wan_carrier` is set. + + Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is + `name` (`str`). + """ + data_plane_cpu_allocation_max: int | None + """ + Set the maximum number of CPU used for the data plane. + This setting is useful on virtual Route + Reflectors and Pathfinders where more CPU cores should be allocated for control plane. + """ + flow_tracker_type: Literal["sampled", "hardware"] | None + """ + Set the flow tracker type. + Override the `default_flow_tracker_type`` set at the `node_type_key` + level. + `default_flow_tracker_type` default value is `sampled`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + group: str | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + id: int | None | UndefinedType = Undefined, + platform: str | None | UndefinedType = Undefined, + mac_address: str | None | UndefinedType = Undefined, + system_mac_address: str | None | UndefinedType = Undefined, + serial_number: str | None | UndefinedType = Undefined, + rack: str | None | UndefinedType = Undefined, + mgmt_ip: str | None | UndefinedType = Undefined, + mgmt_gateway: str | None | UndefinedType = Undefined, + ipv6_mgmt_ip: str | None | UndefinedType = Undefined, + ipv6_mgmt_gateway: str | None | UndefinedType = Undefined, + mgmt_interface: str | None | UndefinedType = Undefined, + link_tracking: LinkTracking | UndefinedType = Undefined, + lacp_port_id_range: LacpPortIdRange | UndefinedType = Undefined, + always_configure_ip_routing: bool | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None | UndefinedType = Undefined, + uplink_ipv4_pool: str | None | UndefinedType = Undefined, + uplink_interfaces: UplinkInterfaces | UndefinedType = Undefined, + uplink_switch_interfaces: UplinkSwitchInterfaces | UndefinedType = Undefined, + uplink_switches: UplinkSwitches | UndefinedType = Undefined, + uplink_interface_speed: str | None | UndefinedType = Undefined, + 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 | UndefinedType = Undefined, + uplink_bfd: bool | UndefinedType = Undefined, + uplink_native_vlan: int | None | UndefinedType = Undefined, + uplink_ptp: UplinkPtp | UndefinedType = Undefined, + uplink_macsec: UplinkMacsec | UndefinedType = Undefined, + uplink_port_channel_id: int | None | UndefinedType = Undefined, + uplink_switch_port_channel_id: int | None | UndefinedType = Undefined, + uplink_structured_config: dict | UndefinedType = Undefined, + mlag_port_channel_structured_config: MlagPortChannelStructuredConfig | UndefinedType = Undefined, + mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig | UndefinedType = Undefined, + mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig | UndefinedType = Undefined, + short_esi: str | None | UndefinedType = Undefined, + isis_system_id_prefix: str | None | UndefinedType = Undefined, + isis_maximum_paths: int | None | UndefinedType = Undefined, + is_type: Literal["level-1-2", "level-1", "level-2"] | None | UndefinedType = Undefined, + node_sid_base: int | UndefinedType = Undefined, + loopback_ipv4_pool: str | None | UndefinedType = Undefined, + loopback_ipv4_address: str | None | UndefinedType = Undefined, + vtep_loopback_ipv4_pool: str | None | UndefinedType = Undefined, + vtep_loopback_ipv4_address: str | None | UndefinedType = Undefined, + loopback_ipv4_offset: int | UndefinedType = Undefined, + loopback_ipv6_pool: str | None | UndefinedType = Undefined, + loopback_ipv6_offset: int | UndefinedType = Undefined, + vtep: bool | None | UndefinedType = Undefined, + vtep_loopback: str | None | UndefinedType = Undefined, + bgp_as: str | None | UndefinedType = Undefined, + bgp_defaults: BgpDefaults | UndefinedType = Undefined, + evpn_role: Literal["client", "server", "none"] | None | UndefinedType = Undefined, + evpn_route_servers: EvpnRouteServers | UndefinedType = Undefined, + evpn_services_l2_only: bool | UndefinedType = Undefined, + filter: Filter | UndefinedType = Undefined, + igmp_snooping_enabled: bool | None | UndefinedType = Undefined, + evpn_gateway: EvpnGateway | UndefinedType = Undefined, + ipvpn_gateway: IpvpnGateway | UndefinedType = Undefined, + mlag: bool | UndefinedType = Undefined, + mlag_dual_primary_detection: bool | UndefinedType = Undefined, + mlag_ibgp_origin_incomplete: bool | UndefinedType = Undefined, + mlag_interfaces: MlagInterfaces | UndefinedType = Undefined, + mlag_interfaces_speed: str | None | UndefinedType = Undefined, + mlag_peer_l3_vlan: int | UndefinedType = Undefined, + mlag_peer_l3_ipv4_pool: str | None | UndefinedType = Undefined, + mlag_peer_vlan: int | UndefinedType = Undefined, + mlag_peer_link_allowed_vlans: str | None | UndefinedType = Undefined, + mlag_peer_address_family: Literal["ipv4", "ipv6"] | UndefinedType = Undefined, + mlag_peer_ipv4_pool: str | None | UndefinedType = Undefined, + mlag_peer_ipv6_pool: str | None | UndefinedType = Undefined, + mlag_port_channel_id: int | None | UndefinedType = Undefined, + mlag_domain_id: str | None | UndefinedType = Undefined, + spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None | UndefinedType = Undefined, + spanning_tree_priority: int | UndefinedType = Undefined, + spanning_tree_root_super: bool | UndefinedType = Undefined, + virtual_router_mac_address: str | None | UndefinedType = Undefined, + inband_mgmt_interface: str | None | UndefinedType = Undefined, + inband_mgmt_vlan: int | UndefinedType = Undefined, + inband_mgmt_subnet: str | None | UndefinedType = Undefined, + inband_mgmt_ip: str | None | UndefinedType = Undefined, + inband_mgmt_gateway: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_address: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_subnet: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_gateway: str | None | UndefinedType = Undefined, + inband_mgmt_description: str | UndefinedType = Undefined, + inband_mgmt_vlan_name: str | UndefinedType = Undefined, + inband_mgmt_vrf: str | UndefinedType = Undefined, + inband_mgmt_mtu: int | UndefinedType = Undefined, + inband_ztp: bool | UndefinedType = Undefined, + inband_ztp_lacp_fallback_delay: int | UndefinedType = Undefined, + mpls_overlay_role: Literal["client", "server", "none"] | None | UndefinedType = Undefined, + overlay_address_families: OverlayAddressFamilies | UndefinedType = Undefined, + mpls_route_reflectors: MplsRouteReflectors | UndefinedType = Undefined, + bgp_cluster_id: str | None | UndefinedType = Undefined, + ptp: Ptp | UndefinedType = Undefined, + wan_role: Literal["client", "server"] | None | UndefinedType = Undefined, + cv_pathfinder_transit_mode: Literal["region", "zone"] | None | UndefinedType = Undefined, + cv_pathfinder_region: str | None | UndefinedType = Undefined, + cv_pathfinder_site: str | None | UndefinedType = Undefined, + wan_ha: WanHa | UndefinedType = Undefined, + dps_mss_ipv4: str | UndefinedType = Undefined, + l3_interfaces: L3Interfaces | UndefinedType = Undefined, + data_plane_cpu_allocation_max: int | None | UndefinedType = Undefined, + flow_tracker_type: Literal["sampled", "hardware"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NodeGroupsItem. + + + Subclass of AvdModel. + + Args: + group: + The Node Group Name is used for MLAG domain unless set with 'mlag_domain_id'. + The Node Group Name is + also used for peer description on downstream switches' uplinks. + nodes: + Define variables per node. + + Subclass of AvdIndexedList with `NodesItem` items. Primary key is `name` + (`str`). + id: Unique identifier used for IP addressing and other algorithms. + platform: Arista platform family. + mac_address: Leverage to document management interface mac address. + system_mac_address: + System MAC Address in this following format: "xx:xx:xx:xx:xx:xx". + Set to the same MAC address as + available in "show version" on the device. + "system_mac_address" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + serial_number: + Set to the Serial Number of the device. + Only used for documentation purpose in the fabric + documentation and part of the structured_config. + "serial_number" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + rack: Rack that the switch is located in (only used in snmp_settings location). + mgmt_ip: Node management interface IPv4 address. + mgmt_gateway: + This key sets the management gateway for the device. It takes precedence over the global + `mgmt_gateway`. + ipv6_mgmt_ip: Node management interface IPv6 address. + ipv6_mgmt_gateway: + This key sets the ipv6 management gateway for the device. It takes precedence over the global + `ipv6_mgmt_gateway`. + mgmt_interface: + Management Interface Name. + Default -> platform_management_interface -> mgmt_interface -> + "Management1". + link_tracking: + This configures the Link Tracking Group on a switch as well as adds the p2p-uplinks of the switch as + the upstream interfaces. + Useful in EVPN multhoming designs. + + + Subclass of AvdModel. + lacp_port_id_range: + This will generate the "lacp port-id range", "begin" and "end" values based on node "id" and the + number of nodes in the "node_group". + Unique LACP port-id ranges are recommended for EVPN Multihoming + designs. + + + Subclass of AvdModel. + always_configure_ip_routing: + Force configuration of "ip routing" even on L2 devices. + Use this to retain behavior of AVD versions + below 4.0.0. + raw_eos_cli: EOS CLI rendered directly on the root level of the final EOS configuration. + structured_config: + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + uplink_type: + Override the default `uplink_type` set at the `node_type_key` level. + `uplink_type` must be "p2p" if + `vtep` or `underlay_router` is true for the `node_type_key` definition. + uplink_ipv4_pool: IPv4 subnet to use to connect to uplink switches. + uplink_interfaces: + Local uplink interfaces. + Each list item supports range syntax that can be expanded into a list of + interfaces. + If uplink_interfaces is not defined, platform-specific defaults (defined under + default_interfaces) will be used instead. + Please note that default_interfaces are not defined by + default, you should define these yourself. + + + Subclass of AvdList with `str` items. + uplink_switch_interfaces: + Interfaces located on uplink switches. + + Subclass of AvdList with `str` items. + uplink_switches: Subclass of AvdList with `str` items. + uplink_interface_speed: + Set point-to-Point interface speed and will apply to uplink interfaces on both ends. + (Uplink switch + interface speed can be overridden with `uplink_switch_interface_speed`). + Speed should be set in the + format `` or `forced ` or `auto `. + uplink_switch_interface_speed: + 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: Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting. + max_uplink_switches: + 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: + 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: Enable bfd on uplink interfaces. + uplink_native_vlan: + 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: + Enable PTP on all infrastructure links. + + Subclass of AvdModel. + uplink_macsec: + Enable MacSec on all uplinks. + + Subclass of AvdModel. + uplink_port_channel_id: + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink Port-channel + ID will be set to the number of the lowest member interface defined under `uplink_interfaces`. + For + example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ Eth11/1, Eth22/1 ] -> ID 111 + For + MLAG port-channels ID will be based on the lowest member interface on the first MLAG switch. + This + option overrides the default behavior and statically sets the local Port-channel ID. + Note! Make sure + the ID is unique and does not overlap with autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between 1 and 2000 and both MLAG switches must have the same + value. + uplink_switch_port_channel_id: + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink switch Port- + channel ID will be set to the number of the first interface defined under + `uplink_switch_interfaces`. + For example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ + Eth11/1, Eth22/1 ] -> ID 111 + For MLAG port-channels ID will be based on the lowest member interface + on the first MLAG switch. + This option overrides the default behavior and statically sets the Port- + channel ID on the uplink switch. + Note! Make sure the ID is unique and does not overlap with + autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between + 1 and 2000 and both MLAG switches must have the same value. + uplink_structured_config: + Custom structured config applied to "uplink_interfaces", and "uplink_switch_interfaces". + When + uplink_type == "p2p", custom structured config added under ethernet_interfaces.[name=] + for eos_cli_config_gen overrides the settings on the ethernet interface level. + When uplink_type == + "port-channel", custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen overrides the settings on the port-channel interface level. + "uplink_structured_config" is applied after "structured_config", so it can override + "structured_config" defined on node-level. + Note! The content of this dictionary is _not_ validated + by the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + mlag_port_channel_structured_config: + Custom structured config applied to MLAG peer link port-channel id. + Added under + port_channel_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the + port-channel interface level. + "mlag_port_channel_structured_config" is applied after + "structured_config", so it can override "structured_config" defined on node-level. + + + Subclass of + AvdModel. + mlag_peer_vlan_structured_config: + Custom structured config applied to MLAG Peer Link (control link) SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_vlan_structured_config" is applied after "structured_config", so it can + override "structured_config" defined on node-level. + + + Subclass of AvdModel. + mlag_peer_l3_vlan_structured_config: + Custom structured config applied to MLAG underlay L3 peering SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_l3_vlan_structured_config" is applied after "structured_config", so it + can override "structured_config" defined on node-level. + + + Subclass of AvdModel. + short_esi: + short_esi only valid for l2leaf devices using port-channel uplink. + Setting short_esi to "auto" + generates the short_esi automatically using a hash of configuration elements. + < 0000:0000:0000 | + auto >. + isis_system_id_prefix: (4.4 hexadecimal). + isis_maximum_paths: Number of path to configure in ECMP for ISIS. + is_type: Overrides `isis_default_is_type`. + node_sid_base: Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID. + loopback_ipv4_pool: IPv4 subnet for Loopback0 allocation. + loopback_ipv4_address: + IPv4 address without mask for Loopback0. + When set, it takes precedence over `loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not catch duplicates. + vtep_loopback_ipv4_pool: IPv4 subnet for VTEP-Loopback allocation. + vtep_loopback_ipv4_address: + IPv4 address without mask for VTEP-Loopback. + When set, it takes precedence over + `vtep_loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not + catch duplicates. + loopback_ipv4_offset: + Offset all assigned loopback IP addresses. + Required when the < loopback_ipv4_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid over-lapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv4_offset: < total # spine switches > or vice versa. + loopback_ipv6_pool: IPv6 subnet for Loopback0 allocation. + loopback_ipv6_offset: + Offset all assigned loopback IPv6 addresses. + Required when the < loopback_ipv6_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid overlapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv6_offset: < total # spine switches > or vice versa. + vtep: + Node is configured as a VTEP when applicable based on 'overlay_routing_protocol'. + Overrides VTEP + setting inherited from node_type_keys. + vtep_loopback: Set VXLAN source interface. + bgp_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + Required with eBGP. + bgp_defaults: + List of EOS commands to apply to BGP daemon. + + Subclass of AvdList with `str` items. + evpn_role: + Acting role in EVPN control plane. + Default is set in node_type definition from node_type_keys. + evpn_route_servers: + List of nodes acting as EVPN Route-Servers / Route-Reflectors. + + Subclass of AvdList with `str` + items. + evpn_services_l2_only: + Possibility to prevent configuration of Tenant VRFs and SVIs. + Override node definition + "network_services_l3" from node_type_keys. + This allows support for centralized routing. + filter: + Filter L3 and L2 network services based on tenant and tags (and operation filter). + If filter is not + defined it will default to all. + + + Subclass of AvdModel. + igmp_snooping_enabled: Activate or deactivate IGMP snooping on device level. + evpn_gateway: + Node is acting as EVPN Multi-Domain Gateway. + New BGP peer-group is generated between EVPN GWs in + different domains or between GWs and Route Servers. + Name can be changed under + "bgp_peer_groups.evpn_overlay_core" variable. + L3 rechability for different EVPN GWs must be already + in place, it is recommended to use DCI & L3 Edge if Route Servers and GWs are not defined under the + same Ansible inventory. + + + Subclass of AvdModel. + ipvpn_gateway: + Node is acting as IP-VPN Gateway for EVPN to MPLS-IP-VPN Interworking. The BGP peer group used for + this is "bgp_peer_groups.ipvpn_gateway_peers". + L3 Reachability is required for this to work, the + preferred method to establish underlay connectivity is to use core_interfaces. + + + Subclass of + AvdModel. + mlag: Enable / Disable auto MLAG, when two nodes are defined in node group. + mlag_dual_primary_detection: Enable / Disable MLAG dual primary detection. + mlag_ibgp_origin_incomplete: + Set origin of routes received from MLAG iBGP peer to incomplete. + The purpose is to optimize routing + for leaf loopbacks from spine perspective and + avoid suboptimal routing via peerlink for control + plane traffic. + mlag_interfaces: + Each list item supports range syntax that can be expanded into a list of interfaces. + Required when + MLAG leafs are present in the topology. + + + Subclass of AvdList with `str` items. + mlag_interfaces_speed: + Set MLAG interface speed. + Speed should be set in the format `` or `forced + ` or `auto `. + mlag_peer_l3_vlan: + Underlay L3 peering SVI interface id. + If set to 0 or the same vlan as mlag_peer_vlan, the + mlag_peer_vlan will be used for L3 peering. + mlag_peer_l3_ipv4_pool: + IP address pool used for MLAG underlay L3 peering. IP is derived from the node id. + Required when + MLAG leafs present in topology and they are using a separate L3 peering VLAN. + mlag_peer_vlan: MLAG Peer Link (control link) SVI interface id. + mlag_peer_link_allowed_vlans: mlag_peer_link_allowed_vlans + mlag_peer_address_family: + IP address family used to establish MLAG Peer Link (control link). + `ipv6` requires EOS version + 4.31.1F or higher. + Note: `ipv6` is not supported in combination with a common MLAG peer link VLAN + (ex. `mlag_peer_l3_vlan` set to 4094). + mlag_peer_ipv4_pool: + IPv4 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv4` (default). + mlag_peer_ipv6_pool: + IPv6 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv6`. + mlag_port_channel_id: + If not set, the mlag port-channel id is generated based on the digits of the first interface present + in 'mlag_interfaces'. + Valid port-channel id numbers are < 1-2000 > for EOS < 4.25.0F and < 1 - + 999999 > for EOS >= 4.25.0F. + mlag_domain_id: MLAG Domain ID. If not set the node group name (Set with "group" key) will be used. + spanning_tree_mode: spanning_tree_mode + spanning_tree_priority: + Spanning-tree priority configured for the selected mode. + For `rapid-pvst` the priority can also be + set per VLAN under network services. + spanning_tree_root_super: spanning_tree_root_super + virtual_router_mac_address: Virtual router mac address for anycast gateway. + inband_mgmt_interface: + Pointer to interface used for inband management. + All configuration must be done using other data + models like network services or structured_config. + 'inband_mgmt_interface' is only used to refer to + this interface as source in various management protocol settings (future feature). + + On L2 switches, + this defaults to Vlan if either 'inband_mgmt_subnet' or 'inband_mgmt_ip' is set. + inband_mgmt_vlan: + VLAN number used for inband management on L2 switches (switches using port-channel trunks as + uplinks). + When using 'inband_mgmt_subnet' the VLAN and SVIs will be created automatically on this + switch as well as all 'uplink_switches'. + When using 'inband_mgmt_ip' the VLAN and SVI will only be + created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be + created using network services data models. + inband_mgmt_subnet: + Optional IP subnet assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ip virtual-router" and host-route injection based on + ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + + 3 + + GW on l2leafs : + 1 + Assign range larger than total l2leafs + 5 + Setting is ignored if 'inband_mgmt_ip' is set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + inband_mgmt_ip: + IP address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_subnet', hence all behavior of 'inband_mgmt_subnet' is removed. + + If this is set the + VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN and SVI on + the parent switches must be created using network services data models. + + This setting is applicable + to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_gateway: + Default gateway configured in the 'inband_mgmt_vrf' when using 'inband_mgmt_ip'. Otherwise gateway + is derived from 'inband_mgmt_subnet' if set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + inband_mgmt_ipv6_address: + IPv6 address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_ipv6_subnet', hence the configuration of 'inband_mgmt_ipv6_subnet' is ignored. + + If this + is set the VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN + and SVI on the parent switches must be created using network services data models. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_ipv6_subnet: + Optional IPv6 prefix assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ipv6 virtual-router" and host-route injection based + on ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN + extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + 3 + + GW on l2leafs : + 1 + Assign range larger than + total l2leafs + 5 + + Setting is ignored if 'inband_mgmt_ipv6_address' is set. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_ipv6_gateway: + Default gateway configured in the 'inband_mgmt_vrf'. + Used when `inband_mgmt_ipv6_address` is set. + Ignored when 'inband_mgmt_ipv6_subnet' is set (first IP in subnet used as gateway). + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_description: + Description configured on the Inband Management SVI. + + This setting is only applied on the devices + where it is set, it does not automatically affect any parent/child devices configuration, so it must + be set on each applicable node/node-group/node-type as needed. + inband_mgmt_vlan_name: + Name configured on the Inband Management VLAN. + This setting is only applied on the devices where it + is set, it does not automatically affect any parent/child devices configuration, so it must be set + on each applicable node/node-group/node-type as needed. + inband_mgmt_vrf: + VRF configured on the Inband Management Interface. + The VRF is created if not already created by + other means. + This setting is only applied on the devices where it is set, it does not automatically + affect any parent/child devices configuration, so it must be set on each applicable node/node- + group/node-type as needed. + inband_mgmt_mtu: + MTU configured on the Inband Management Interface. + This setting is only applied on the devices where + it is set, it does not automatically affect any parent/child devices configuration, so it must be + set on each applicable node/node-group/node-type as needed. + inband_ztp: + Enable to configure upstream device with proper configuration to allow downstream devices to be + Zero-Touch-Provisioned over the uplink interfaces. + For L2 devices this setting also requires that + the `inband_mgmt_vlan` is set for the node. + + PREVIEW: Support for L3 devices is marked as "preview", + meaning the data models or generated configuration can change at any time. + inband_ztp_lacp_fallback_delay: + Set the LACP fallback timeout of the upstream device's port-channel towards the downstream inband + ZTP node. + This setting also requires that `inband_ztp` is set for the node. + mpls_overlay_role: + Set the default mpls overlay role. + Acting role in overlay control plane. + overlay_address_families: + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + mpls_route_reflectors: + List of inventory hostname acting as MPLS route-reflectors. + + Subclass of AvdList with `str` items. + bgp_cluster_id: Set BGP cluster id. + ptp: Subclass of AvdModel. + wan_role: + Override the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + cv_pathfinder_transit_mode: + Configure the transit mode for a WAN client for CV Pathfinder designs + only when the `wan_mode` root + key is set to `cv_pathfinder`. + + 'zone' is currently not supported. + cv_pathfinder_region: + The CV Pathfinder region name. + This key is required for WAN routers but optional for pathfinders. + The region name must be defined under 'cv_pathfinder_regions'. + cv_pathfinder_site: + The CV Pathfinder site name. + This key is required for WAN routers but optional for pathfinders. + For + WAN routers and pathfinders with `cv_pathfinder_region`, the site name must be defined for the + relevant region under 'cv_pathfinder_regions'. + For pathfinders without `cv_pathfinder_region` set, + the site must be defined under `cv_pathfinder_global_sites`. + wan_ha: + PREVIEW: This key is currently not supported + + The key is supported only if `wan_mode` == `cv- + pathfinder`. + AutoVPN support is still to be determined. + + Maximum 2 devices supported by group for + HA. + + Subclass of AvdModel. + dps_mss_ipv4: IPv4 MSS value configured under "router path-selection" on WAN Devices. + l3_interfaces: + L3 Interfaces to configure on the node. + Used to define the node for WAN interfaces when + `wan_carrier` is set. + + Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is + `name` (`str`). + data_plane_cpu_allocation_max: + Set the maximum number of CPU used for the data plane. + This setting is useful on virtual Route + Reflectors and Pathfinders where more CPU cores should be allocated for control plane. + flow_tracker_type: + Set the flow tracker type. + Override the `default_flow_tracker_type`` set at the `node_type_key` + level. + `default_flow_tracker_type` default value is `sampled`. + _custom_data: _custom_data + + """ + + class NodeGroups(AvdIndexedList[str, NodeGroupsItem]): + """Subclass of AvdIndexedList with `NodeGroupsItem` items. Primary key is `group` (`str`).""" + + _primary_key: ClassVar[str] = "group" + + NodeGroups._item_type = NodeGroupsItem + + class NodesItem(AvdModel): + """Subclass of AvdModel.""" + + class DownlinkPoolsItem(AvdModel): + """Subclass of AvdModel.""" + + class DownlinkInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DownlinkInterfaces._item_type = str + + _fields: ClassVar[dict] = { + "ipv4_pool": {"type": str}, + "downlink_interfaces": {"type": DownlinkInterfaces}, + "_custom_data": {"type": dict}, + } + ipv4_pool: str | None + """IPv4 pool from which subnets will be allocated for links to downlink switches.""" + downlink_interfaces: DownlinkInterfaces + """ + List of downlink interfaces or ranges of interfaces to use this pool. The index of the interface in + this list will determine which subnet will be taken from the pool. + + Subclass of AvdList with `str` + items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4_pool: str | None | UndefinedType = Undefined, + downlink_interfaces: DownlinkInterfaces | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DownlinkPoolsItem. + + + Subclass of AvdModel. + + Args: + ipv4_pool: IPv4 pool from which subnets will be allocated for links to downlink switches. + downlink_interfaces: + List of downlink interfaces or ranges of interfaces to use this pool. The index of the interface in + this list will determine which subnet will be taken from the pool. + + Subclass of AvdList with `str` + items. + _custom_data: _custom_data + + """ + + class DownlinkPools(AvdList[DownlinkPoolsItem]): + """Subclass of AvdList with `DownlinkPoolsItem` items.""" + + DownlinkPools._item_type = DownlinkPoolsItem + + class LinkTracking(AvdModel): + """Subclass of AvdModel.""" + + class GroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "recovery_delay": {"type": int}, + "links_minimum": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str | None + """Tracking group name.""" + recovery_delay: int | None + """default -> platform_settings_mlag_reload_delay -> 300.""" + links_minimum: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + recovery_delay: int | None | UndefinedType = Undefined, + links_minimum: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GroupsItem. + + + Subclass of AvdModel. + + Args: + name: Tracking group name. + recovery_delay: default -> platform_settings_mlag_reload_delay -> 300. + links_minimum: links_minimum + _custom_data: _custom_data + + """ + + class Groups(AvdList[GroupsItem]): + """Subclass of AvdList with `GroupsItem` items.""" + + Groups._item_type = GroupsItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "groups": {"type": Groups, "default": lambda cls: coerce_type([{"name": "LT_GROUP1"}], target_type=cls)}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + groups: Groups + """ + Link Tracking Groups. + By default a single group named "LT_GROUP1" is defined with default values. + Any groups defined under "groups" will replace the default. + + + Subclass of AvdList with `GroupsItem` + items. + + Default value: `lambda cls: coerce_type([{"name": "LT_GROUP1"}], target_type=cls)` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + groups: + Link Tracking Groups. + By default a single group named "LT_GROUP1" is defined with default values. + Any groups defined under "groups" will replace the default. + + + Subclass of AvdList with `GroupsItem` + items. + _custom_data: _custom_data + + """ + + class LacpPortIdRange(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "size": {"type": int, "default": 128}, + "offset": {"type": int, "default": 0}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + size: int + """ + Recommended size > = number of ports in the switch. + + Default value: `128` + """ + offset: int + """ + Offset is used to avoid overlapping port-id ranges of different switches. + Useful when a "connected- + endpoint" is connected to switches in different "node_groups". + + Default value: `0` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + size: int | UndefinedType = Undefined, + offset: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LacpPortIdRange. + + + Subclass of AvdModel. + + Args: + enabled: enabled + size: Recommended size > = number of ports in the switch. + offset: + Offset is used to avoid overlapping port-id ranges of different switches. + Useful when a "connected- + endpoint" is connected to switches in different "node_groups". + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen): + """Subclass of AvdModel.""" + + class UplinkInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkInterfaces._item_type = str + + class UplinkSwitchInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkSwitchInterfaces._item_type = str + + class UplinkSwitches(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkSwitches._item_type = str + + class UplinkPtp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enable": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enable: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, enable: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + UplinkPtp. + + + Subclass of AvdModel. + + Args: + enable: enable + _custom_data: _custom_data + + """ + + class UplinkMacsec(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "_custom_data": {"type": dict}} + profile: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, profile: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + UplinkMacsec. + + + Subclass of AvdModel. + + Args: + profile: profile + _custom_data: _custom_data + + """ + + class MlagPortChannelStructuredConfig(EosCliConfigGen.PortChannelInterfacesItem): + """Subclass of AvdModel.""" + + class MlagPeerVlanStructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + class MlagPeerL3VlanStructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + class BgpDefaults(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + BgpDefaults._item_type = str + + class EvpnRouteServers(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + EvpnRouteServers._item_type = str + + class Filter(AvdModel): + """Subclass of AvdModel.""" + + class Tenants(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tenants._item_type = str + + class Tags(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tags._item_type = str + + class AllowVrfs(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AllowVrfs._item_type = str + + class DenyVrfs(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DenyVrfs._item_type = str + + class AlwaysIncludeVrfsInTenants(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AlwaysIncludeVrfsInTenants._item_type = str + + _fields: ClassVar[dict] = { + "tenants": {"type": Tenants, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "tags": {"type": Tags, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "allow_vrfs": {"type": AllowVrfs, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "deny_vrfs": {"type": DenyVrfs, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "always_include_vrfs_in_tenants": {"type": AlwaysIncludeVrfsInTenants}, + "only_vlans_in_use": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + tenants: Tenants + """ + Limit configured Network Services to those defined under these Tenants. Set to ['all'] for all + Tenants (default). + This list also limits Tenants included by `always_include_vrfs_in_tenants`. + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + tags: Tags + """ + Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default). + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + allow_vrfs: AllowVrfs + """ + Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs + (default). + This list also limits VRFs included by `always_include_vrfs_in_tenants`. + + Subclass of + AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + deny_vrfs: DenyVrfs + """ + Prevent configuration of Network Services defined under these VRFs. + This list prevents the given + VRFs to be included by any other filtering mechanism. + + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + always_include_vrfs_in_tenants: AlwaysIncludeVrfsInTenants + """ + List of tenants where VRFs will be configured even if VLANs are not included in tags. + Useful for L3 + "border" leaf. + + + Subclass of AvdList with `str` items. + """ + only_vlans_in_use: bool + """ + Only configure VLANs, SVIs, VRFs in use by connected endpoints or downstream L2 switches. + Note! This + feature only considers configuration managed by eos_designs. + This excludes structured_config, + custom_structured_configuration_, raw_eos_cli, eos_cli, custom templates, configlets etc. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + tenants: Tenants | UndefinedType = Undefined, + tags: Tags | UndefinedType = Undefined, + allow_vrfs: AllowVrfs | UndefinedType = Undefined, + deny_vrfs: DenyVrfs | UndefinedType = Undefined, + always_include_vrfs_in_tenants: AlwaysIncludeVrfsInTenants | UndefinedType = Undefined, + only_vlans_in_use: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Filter. + + + Subclass of AvdModel. + + Args: + tenants: + Limit configured Network Services to those defined under these Tenants. Set to ['all'] for all + Tenants (default). + This list also limits Tenants included by `always_include_vrfs_in_tenants`. + Subclass of AvdList with `str` items. + tags: + Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default). + Subclass of AvdList with `str` items. + allow_vrfs: + Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs + (default). + This list also limits VRFs included by `always_include_vrfs_in_tenants`. + + Subclass of + AvdList with `str` items. + deny_vrfs: + Prevent configuration of Network Services defined under these VRFs. + This list prevents the given + VRFs to be included by any other filtering mechanism. + + Subclass of AvdList with `str` items. + always_include_vrfs_in_tenants: + List of tenants where VRFs will be configured even if VLANs are not included in tags. + Useful for L3 + "border" leaf. + + + Subclass of AvdList with `str` items. + only_vlans_in_use: + Only configure VLANs, SVIs, VRFs in use by connected endpoints or downstream L2 switches. + Note! This + feature only considers configuration managed by eos_designs. + This excludes structured_config, + custom_structured_configuration_, raw_eos_cli, eos_cli, custom templates, configlets etc. + _custom_data: _custom_data + + """ + + class EvpnGateway(AvdModel): + """Subclass of AvdModel.""" + + class RemotePeersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hostname": {"type": str}, + "ip_address": {"type": str}, + "bgp_as": {"type": str}, + "_custom_data": {"type": dict}, + } + hostname: str + """Hostname of remote EVPN GW server.""" + ip_address: str | None + """Peering IP of remote Route Server.""" + bgp_as: str | None + """ + Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being + interpreted as a float number. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: str | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + bgp_as: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemotePeersItem. + + + Subclass of AvdModel. + + Args: + hostname: Hostname of remote EVPN GW server. + ip_address: Peering IP of remote Route Server. + bgp_as: + Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being + interpreted as a float number. + _custom_data: _custom_data + + """ + + class RemotePeers(AvdIndexedList[str, RemotePeersItem]): + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + + _primary_key: ClassVar[str] = "hostname" + + RemotePeers._item_type = RemotePeersItem + + class EvpnL2(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enabled: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, enabled: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + EvpnL2. + + + Subclass of AvdModel. + + Args: + enabled: enabled + _custom_data: _custom_data + + """ + + class EvpnL3(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "inter_domain": {"type": bool, "default": True}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + inter_domain: bool + """Default value: `True`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + inter_domain: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnL3. + + + Subclass of AvdModel. + + Args: + enabled: enabled + inter_domain: inter_domain + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "remote_peers": {"type": RemotePeers}, + "evpn_l2": {"type": EvpnL2}, + "evpn_l3": {"type": EvpnL3}, + "_custom_data": {"type": dict}, + } + remote_peers: RemotePeers + """ + Define remote peers of the EVPN VXLAN Gateway. + If the hostname can be found in the inventory, + ip_address and BGP ASN will be automatically populated. Manual override takes precedence. + If the + peer's hostname can not be found in the inventory, ip_address and bgp_as must be defined. + + + Subclass + of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + """ + evpn_l2: EvpnL2 + """ + Enable EVPN Gateway functionality for route-types 2 (MAC-IP) and 3 (IMET). + + Subclass of AvdModel. + """ + evpn_l3: EvpnL3 + """ + Enable EVPN Gateway functionality for route-type 5 (IP-PREFIX). + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + remote_peers: RemotePeers | UndefinedType = Undefined, + evpn_l2: EvpnL2 | UndefinedType = Undefined, + evpn_l3: EvpnL3 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnGateway. + + + Subclass of AvdModel. + + Args: + remote_peers: + Define remote peers of the EVPN VXLAN Gateway. + If the hostname can be found in the inventory, + ip_address and BGP ASN will be automatically populated. Manual override takes precedence. + If the + peer's hostname can not be found in the inventory, ip_address and bgp_as must be defined. + + + Subclass + of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + evpn_l2: + Enable EVPN Gateway functionality for route-types 2 (MAC-IP) and 3 (IMET). + + Subclass of AvdModel. + evpn_l3: + Enable EVPN Gateway functionality for route-type 5 (IP-PREFIX). + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class IpvpnGateway(AvdModel): + """Subclass of AvdModel.""" + + class AddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AddressFamilies._item_type = str + + class RemotePeersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hostname": {"type": str}, + "ip_address": {"type": str}, + "bgp_as": {"type": str}, + "_custom_data": {"type": dict}, + } + hostname: str + """Hostname of remote IPVPN Peer.""" + ip_address: str + """Peering IP of remote IPVPN Peer.""" + bgp_as: str + """ + Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For + asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted + as a float number. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: str | UndefinedType = Undefined, + ip_address: str | UndefinedType = Undefined, + bgp_as: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemotePeersItem. + + + Subclass of AvdModel. + + Args: + hostname: Hostname of remote IPVPN Peer. + ip_address: Peering IP of remote IPVPN Peer. + bgp_as: + Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For + asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted + as a float number. + _custom_data: _custom_data + + """ + + class RemotePeers(AvdIndexedList[str, RemotePeersItem]): + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + + _primary_key: ClassVar[str] = "hostname" + + RemotePeers._item_type = RemotePeersItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "evpn_domain_id": {"type": str, "default": "65535:1"}, + "ipvpn_domain_id": {"type": str, "default": "65535:2"}, + "enable_d_path": {"type": bool, "default": True}, + "maximum_routes": {"type": int, "default": 0}, + "local_as": {"type": str}, + "address_families": {"type": AddressFamilies, "default": lambda cls: coerce_type(["vpn-ipv4"], target_type=cls)}, + "remote_peers": {"type": RemotePeers}, + "_custom_data": {"type": dict}, + } + enabled: bool + evpn_domain_id: str + """ + Domain ID to assign to EVPN address family for use with D-path. Format :. + + Default value: `"65535:1"` + """ + ipvpn_domain_id: str + """ + Domain ID to assign to IPVPN address families for use with D-path. Format :. + + Default value: `"65535:2"` + """ + enable_d_path: bool + """ + Enable D-path for use with BGP bestpath selection algorithm. + + Default value: `True` + """ + maximum_routes: int + """ + Maximum routes to accept from IPVPN remote peers. + + Default value: `0` + """ + local_as: str | None + """ + Local BGP AS applied to peering with IPVPN remote peers. + BGP AS <1-4294967295> or AS number in asdot + notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number. + """ + address_families: AddressFamilies + """ + IPVPN address families to enable for remote peers. + + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["vpn-ipv4"], target_type=cls)` + """ + remote_peers: RemotePeers + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + evpn_domain_id: str | UndefinedType = Undefined, + ipvpn_domain_id: str | UndefinedType = Undefined, + enable_d_path: bool | UndefinedType = Undefined, + maximum_routes: int | UndefinedType = Undefined, + local_as: str | None | UndefinedType = Undefined, + address_families: AddressFamilies | UndefinedType = Undefined, + remote_peers: RemotePeers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpvpnGateway. + + + Subclass of AvdModel. + + Args: + enabled: enabled + evpn_domain_id: Domain ID to assign to EVPN address family for use with D-path. Format :. + ipvpn_domain_id: Domain ID to assign to IPVPN address families for use with D-path. Format :. + enable_d_path: Enable D-path for use with BGP bestpath selection algorithm. + maximum_routes: Maximum routes to accept from IPVPN remote peers. + local_as: + Local BGP AS applied to peering with IPVPN remote peers. + BGP AS <1-4294967295> or AS number in asdot + notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number. + address_families: + IPVPN address families to enable for remote peers. + + Subclass of AvdList with `str` items. + remote_peers: Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + _custom_data: _custom_data + + """ + + class MlagInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MlagInterfaces._item_type = str + + class OverlayAddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + OverlayAddressFamilies._item_type = str + + class MplsRouteReflectors(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MplsRouteReflectors._item_type = str + + class Ptp(AvdModel): + """Subclass of AvdModel.""" + + class Dscp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"general_messages": {"type": int}, "event_messages": {"type": int}, "_custom_data": {"type": dict}} + general_messages: int | None + event_messages: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + general_messages: int | None | UndefinedType = Undefined, + event_messages: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dscp. + + + Subclass of AvdModel. + + Args: + general_messages: general_messages + event_messages: event_messages + _custom_data: _custom_data + + """ + + class Monitor(AvdModel): + """Subclass of AvdModel.""" + + class Threshold(AvdModel): + """Subclass of AvdModel.""" + + class Drop(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "offset_from_master": {"type": int}, + "mean_path_delay": {"type": int}, + "_custom_data": {"type": dict}, + } + offset_from_master: int | None + mean_path_delay: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + offset_from_master: int | None | UndefinedType = Undefined, + mean_path_delay: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Drop. + + + Subclass of AvdModel. + + Args: + offset_from_master: offset_from_master + mean_path_delay: mean_path_delay + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "offset_from_master": {"type": int, "default": 250}, + "mean_path_delay": {"type": int, "default": 1500}, + "drop": {"type": Drop}, + "_custom_data": {"type": dict}, + } + offset_from_master: int + """Default value: `250`""" + mean_path_delay: int + """Default value: `1500`""" + drop: Drop + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + offset_from_master: int | UndefinedType = Undefined, + mean_path_delay: int | UndefinedType = Undefined, + drop: Drop | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Threshold. + + + Subclass of AvdModel. + + Args: + offset_from_master: offset_from_master + mean_path_delay: mean_path_delay + drop: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MissingMessage(AvdModel): + """Subclass of AvdModel.""" + + class Intervals(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "announce": {"type": int}, + "follow_up": {"type": int}, + "sync": {"type": int}, + "_custom_data": {"type": dict}, + } + announce: int | None + follow_up: int | None + sync: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + announce: int | None | UndefinedType = Undefined, + follow_up: int | None | UndefinedType = Undefined, + sync: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Intervals. + + + Subclass of AvdModel. + + Args: + announce: announce + follow_up: follow_up + sync: sync + _custom_data: _custom_data + + """ + + class SequenceIds(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "announce": {"type": int, "default": 3}, + "delay_resp": {"type": int, "default": 3}, + "follow_up": {"type": int, "default": 3}, + "sync": {"type": int, "default": 3}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + announce: int + """Default value: `3`""" + delay_resp: int + """Default value: `3`""" + follow_up: int + """Default value: `3`""" + sync: int + """Default value: `3`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + announce: int | UndefinedType = Undefined, + delay_resp: int | UndefinedType = Undefined, + follow_up: int | UndefinedType = Undefined, + sync: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceIds. + + + Subclass of AvdModel. + + Args: + enabled: enabled + announce: announce + delay_resp: delay_resp + follow_up: follow_up + sync: sync + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "intervals": {"type": Intervals}, + "sequence_ids": {"type": SequenceIds}, + "_custom_data": {"type": dict}, + } + intervals: Intervals + """Subclass of AvdModel.""" + sequence_ids: SequenceIds + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + intervals: Intervals | UndefinedType = Undefined, + sequence_ids: SequenceIds | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingMessage. + + + Subclass of AvdModel. + + Args: + intervals: Subclass of AvdModel. + sequence_ids: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "threshold": {"type": Threshold}, + "missing_message": {"type": MissingMessage}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + threshold: Threshold + """Subclass of AvdModel.""" + missing_message: MissingMessage + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + threshold: Threshold | UndefinedType = Undefined, + missing_message: MissingMessage | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Monitor. + + + Subclass of AvdModel. + + Args: + enabled: enabled + threshold: Subclass of AvdModel. + missing_message: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "profile": {"type": str}, + "mlag": {"type": bool, "default": False}, + "domain": {"type": int, "default": 127}, + "priority1": {"type": int}, + "priority2": {"type": int}, + "auto_clock_identity": {"type": bool}, + "clock_identity_prefix": {"type": str, "default": "00:1C:73"}, + "clock_identity": {"type": str}, + "source_ip": {"type": str}, + "mode": {"type": str, "default": "boundary"}, + "mode_one_step": {"type": bool, "default": False}, + "ttl": {"type": int}, + "forward_unicast": {"type": bool, "default": False}, + "dscp": {"type": Dscp}, + "monitor": {"type": Monitor}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + profile: str | None + """ + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + """ + mlag: bool + """ + Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be + configured on the MLAG peer-link port-channel. + + Default value: `False` + """ + domain: int + """Default value: `127`""" + priority1: int | None + """default -> automatically set based on node_type.""" + priority2: int | None + """default -> (node_id modulus 256).""" + auto_clock_identity: bool | None + """ + If you prefer to have PTP clock identity be the system MAC-address of the switch, which is the + default EOS behaviour, simply disable the automatic PTP clock identity. + default -> + (clock_identity_prefix = 00:1C:73 (default)) + (PTP priority 1 as HEX) + ":00:" + (PTP priority 2 as + HEX). + """ + clock_identity_prefix: str + """ + PTP clock idetentiy 3-byte prefix. i.e. "01:02:03". + By default the 3-byte prefix is "00:1C:73". + This + can be overridden if auto_clock_identity is set to true (which is the default). + + Default value: `"00:1C:73"` + """ + clock_identity: str | None + """Set PTP clock identity manually. 6-byte value i.e. "01:02:03:04:05:06".""" + source_ip: str | None + """ + By default in EOS, PTP packets are sourced with an IP address from the routed port or from the + relevant SVI, which is the recommended behaviour. + This can be set manually if required, for example, + to a value of "10.1.2.3". + """ + mode: Literal["boundary"] + """Default value: `"boundary"`""" + mode_one_step: bool + """Default value: `False`""" + ttl: int | None + forward_unicast: bool + """ + Enable PTP unicast forwarding. + + Default value: `False` + """ + dscp: Dscp + """Subclass of AvdModel.""" + monitor: Monitor + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + profile: str | None | UndefinedType = Undefined, + mlag: bool | UndefinedType = Undefined, + domain: int | UndefinedType = Undefined, + priority1: int | None | UndefinedType = Undefined, + priority2: int | None | UndefinedType = Undefined, + auto_clock_identity: bool | None | UndefinedType = Undefined, + clock_identity_prefix: str | UndefinedType = Undefined, + clock_identity: str | None | UndefinedType = Undefined, + source_ip: str | None | UndefinedType = Undefined, + mode: Literal["boundary"] | UndefinedType = Undefined, + mode_one_step: bool | UndefinedType = Undefined, + ttl: int | None | UndefinedType = Undefined, + forward_unicast: bool | UndefinedType = Undefined, + dscp: Dscp | UndefinedType = Undefined, + monitor: Monitor | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ptp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + profile: + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + mlag: + Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be + configured on the MLAG peer-link port-channel. + domain: domain + priority1: default -> automatically set based on node_type. + priority2: default -> (node_id modulus 256). + auto_clock_identity: + If you prefer to have PTP clock identity be the system MAC-address of the switch, which is the + default EOS behaviour, simply disable the automatic PTP clock identity. + default -> + (clock_identity_prefix = 00:1C:73 (default)) + (PTP priority 1 as HEX) + ":00:" + (PTP priority 2 as + HEX). + clock_identity_prefix: + PTP clock idetentiy 3-byte prefix. i.e. "01:02:03". + By default the 3-byte prefix is "00:1C:73". + This + can be overridden if auto_clock_identity is set to true (which is the default). + clock_identity: Set PTP clock identity manually. 6-byte value i.e. "01:02:03:04:05:06". + source_ip: + By default in EOS, PTP packets are sourced with an IP address from the routed port or from the + relevant SVI, which is the recommended behaviour. + This can be set manually if required, for example, + to a value of "10.1.2.3". + mode: mode + mode_one_step: mode_one_step + ttl: ttl + forward_unicast: Enable PTP unicast forwarding. + dscp: Subclass of AvdModel. + monitor: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class WanHa(AvdModel): + """Subclass of AvdModel.""" + + class HaInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + HaInterfaces._item_type = str + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "ipsec": {"type": bool, "default": True}, + "mtu": {"type": int, "default": 9194}, + "ha_interfaces": {"type": HaInterfaces}, + "ha_ipv4_pool": {"type": str}, + "max_ha_interfaces": {"type": int}, + "port_channel_id": {"type": int}, + "use_port_channel_for_direct_ha": {"type": bool, "default": True}, + "flow_tracking": {"type": FlowTracking}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group.""" + ipsec: bool + """ + Enable / Disable IPsec over HA path-group when HA is enabled. + + Default value: `True` + """ + mtu: int + """ + Set MTU on WAN HA interfaces. + + Default value: `9194` + """ + ha_interfaces: HaInterfaces + """ + Local WAN HA interfaces + Overwrite the default behavior which is to pick all the `uplink_interfaces`. + Can be used to filter uplink interfaces when there are multiple uplinks. + Limitations: + Either all + interfaces must be uplinks or all interfaces must not be uplinks. + Only one interface is supported + for non uplinks. + + Subclass of AvdList with `str` items. + """ + ha_ipv4_pool: str | None + """ + IP address pool used for WAN HA connectivity. + IP is derived from the node ID. + Not used for uplink + interfaces. + """ + max_ha_interfaces: int | None + """ + Number of parallel links towards HA switches. + Can be used to reserve IP addresses for future + parallel HA links. + """ + port_channel_id: int | None + """Port-channel ID to use for direct HA.""" + use_port_channel_for_direct_ha: bool + """ + Enable or disable using a port-channel interface for direct HA when there is only one interface. + This feature was introduced in EOS 4.33.0F. + + Default value: `True` + """ + flow_tracking: FlowTracking + """ + Configures flow-tracking on the HA interfaces. Overrides `fabric_flow_tracking.wan_ha_links` + setting. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + ipsec: bool | UndefinedType = Undefined, + mtu: int | UndefinedType = Undefined, + ha_interfaces: HaInterfaces | UndefinedType = Undefined, + ha_ipv4_pool: str | None | UndefinedType = Undefined, + max_ha_interfaces: int | None | UndefinedType = Undefined, + port_channel_id: int | None | UndefinedType = Undefined, + use_port_channel_for_direct_ha: bool | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + WanHa. + + + Subclass of AvdModel. + + Args: + enabled: Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group. + ipsec: Enable / Disable IPsec over HA path-group when HA is enabled. + mtu: Set MTU on WAN HA interfaces. + ha_interfaces: + Local WAN HA interfaces + Overwrite the default behavior which is to pick all the `uplink_interfaces`. + Can be used to filter uplink interfaces when there are multiple uplinks. + Limitations: + Either all + interfaces must be uplinks or all interfaces must not be uplinks. + Only one interface is supported + for non uplinks. + + Subclass of AvdList with `str` items. + ha_ipv4_pool: + IP address pool used for WAN HA connectivity. + IP is derived from the node ID. + Not used for uplink + interfaces. + max_ha_interfaces: + Number of parallel links towards HA switches. + Can be used to reserve IP addresses for future + parallel HA links. + port_channel_id: Port-channel ID to use for direct HA. + use_port_channel_for_direct_ha: + Enable or disable using a port-channel interface for direct HA when there is only one interface. + This feature was introduced in EOS 4.33.0F. + flow_tracking: + Configures flow-tracking on the HA interfaces. Overrides `fabric_flow_tracking.wan_ha_links` + setting. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L3InterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "peer_as": {"type": str}, + "ipv4_prefix_list_in": {"type": str}, + "ipv4_prefix_list_out": {"type": str}, + "_custom_data": {"type": dict}, + } + peer_as: str + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + ipv4_prefix_list_in: str | None + """ + Prefix List Name. Accept routes for only these prefixes from the peer. + Required for wan interfaces. + """ + ipv4_prefix_list_out: str | None + """ + Prefix List Name. Advertise routes for only these prefixes. + If not specified, nothing would be + advertised. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + peer_as: str | UndefinedType = Undefined, + ipv4_prefix_list_in: str | None | UndefinedType = Undefined, + ipv4_prefix_list_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + peer_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + ipv4_prefix_list_in: + Prefix List Name. Accept routes for only these prefixes from the peer. + Required for wan interfaces. + ipv4_prefix_list_out: + Prefix List Name. Advertise routes for only these prefixes. + If not specified, nothing would be + advertised. + _custom_data: _custom_data + + """ + + class StaticRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "_custom_data": {"type": dict}} + prefix: str + """IPv4_network/Mask.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, prefix: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + StaticRoutesItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv4_network/Mask. + _custom_data: _custom_data + + """ + + class StaticRoutes(AvdList[StaticRoutesItem]): + """Subclass of AvdList with `StaticRoutesItem` items.""" + + StaticRoutes._item_type = StaticRoutesItem + + class CvPathfinderInternetExit(AvdModel): + """Subclass of AvdModel.""" + + class PoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "tunnel_interface_numbers": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Internet-exit policy name.""" + tunnel_interface_numbers: str | None + """ + Number range to use for Tunnel interfaces to an internet-exit service provider using this local + interface. + Examples: '1-3' or '100,200,300' + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + tunnel_interface_numbers: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PoliciesItem. + + + Subclass of AvdModel. + + Args: + name: Internet-exit policy name. + tunnel_interface_numbers: + Number range to use for Tunnel interfaces to an internet-exit service provider using this local + interface. + Examples: '1-3' or '100,200,300' + _custom_data: _custom_data + + """ + + class Policies(AvdIndexedList[str, PoliciesItem]): + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Policies._item_type = PoliciesItem + + _fields: ClassVar[dict] = {"policies": {"type": Policies}, "_custom_data": {"type": dict}} + policies: Policies + """ + List of Internet-exit policies using this interface as exit. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, policies: Policies | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + CvPathfinderInternetExit. + + + Subclass of AvdModel. + + Args: + policies: + List of Internet-exit policies using this interface as exit. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "profile": {"type": str}, + "name": {"type": str}, + "description": {"type": str}, + "ip_address": {"type": str}, + "dhcp_ip": {"type": str}, + "public_ip": {"type": str}, + "encapsulation_dot1q_vlan": {"type": int}, + "dhcp_accept_default_route": {"type": bool, "default": True}, + "enabled": {"type": bool, "default": True}, + "speed": {"type": str}, + "peer": {"type": str}, + "peer_interface": {"type": str}, + "peer_ip": {"type": str}, + "bgp": {"type": Bgp}, + "ipv4_acl_in": {"type": str}, + "ipv4_acl_out": {"type": str}, + "static_routes": {"type": StaticRoutes}, + "qos_profile": {"type": str}, + "wan_carrier": {"type": str}, + "wan_circuit_id": {"type": str}, + "connected_to_pathfinder": {"type": bool, "default": True}, + "cv_pathfinder_internet_exit": {"type": CvPathfinderInternetExit}, + "raw_eos_cli": {"type": str}, + "flow_tracking": {"type": FlowTracking}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + profile: str | None + """L3 interface profile name. Profile defined under `l3_interface_profiles`.""" + name: str + """ + Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. + For a + subinterface, the parent physical interface is automatically created. + """ + description: str | None + """ + Interface description. + If not set a default description will be configured with '[[ + ]]'. + """ + ip_address: str | None + """Node IPv4 address/Mask or 'dhcp'.""" + dhcp_ip: str | None + """ + When the `ip_address` is `dhcp`, this optional field allows to indicate the expected + IPv4 address + (without mask) to be allocated on the interface if known. + This is not rendered in the configuration + but can be used for substitution of 'interface_ip' in the Access-list + set under `ipv4_acl_in` and + `ipv4_acl_out`. + """ + public_ip: str | None + """ + Node IPv4 address (no mask). + + This is used to get the public IP (if known) when the device is behind + NAT. + This is only used for `wan_rr` routers (AutoVPN RRs and Pathfinders) to determine the Public IP + with the following preference: + `wan_route_servers.path_groups.interfaces.ip_address` + -> + `l3_interfaces.public_ip` + -> `l3_interfaces.ip_address` + + The determined Public IP is used + by WAN routers when peering with this interface. + """ + encapsulation_dot1q_vlan: int | None + """ + For subinterfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + """ + dhcp_accept_default_route: bool + """ + Accept a default route from DHCP if `ip_address` is set to `dhcp`. + + Default value: `True` + """ + enabled: bool + """ + Enable or Shutdown the interface. + + Default value: `True` + """ + speed: str | None + """ + Speed should be set in the format `` or `forced ` or `auto + `. + """ + peer: str | None + """The peer device name. Used for description and documentation.""" + peer_interface: str | None + """The peer device interface. Used for description and documentation.""" + peer_ip: str | None + """ + The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true + and `ip` is an IP address. + """ + bgp: Bgp + """ + Enforce IPv4 BGP peering for the peer + + Subclass of AvdModel. + """ + ipv4_acl_in: str | None + """ + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + Required + for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under + `wan_carriers`. + """ + ipv4_acl_out: str | None + """ + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + """ + static_routes: StaticRoutes + """ + Configure IPv4 static routes pointing to `peer_ip`. + + Subclass of AvdList with `StaticRoutesItem` + items. + """ + qos_profile: str | None + """QOS service profile.""" + wan_carrier: str | None + """ + The WAN carrier this interface is connected to. + This is used to infer the path-groups in which this + interface should be configured. + Unless the carrier is marked as 'trusted' under `wan_carriers`, + `ipv4_acl_in` is also required on all WAN interfaces. + """ + wan_circuit_id: str | None + """ + The WAN circuit ID for this interface. + This is not rendered in the configuration but used for WAN + designs. + """ + connected_to_pathfinder: bool + """ + For a WAN interface (`wan_carrier` is set), allow to disable the static tunnel towards Pathfinders. + + Default value: `True` + """ + cv_pathfinder_internet_exit: CvPathfinderInternetExit + """ + PREVIEW: This key is in preview mode + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the interface in the final EOS configuration.""" + flow_tracking: FlowTracking + """ + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + """ + structured_config: StructuredConfig + """ + Custom structured config for the Ethernet interface. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | None | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + dhcp_ip: str | None | UndefinedType = Undefined, + public_ip: str | None | UndefinedType = Undefined, + encapsulation_dot1q_vlan: int | None | UndefinedType = Undefined, + dhcp_accept_default_route: bool | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + speed: str | None | UndefinedType = Undefined, + peer: str | None | UndefinedType = Undefined, + peer_interface: str | None | UndefinedType = Undefined, + peer_ip: str | None | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + ipv4_acl_in: str | None | UndefinedType = Undefined, + ipv4_acl_out: str | None | UndefinedType = Undefined, + static_routes: StaticRoutes | UndefinedType = Undefined, + qos_profile: str | None | UndefinedType = Undefined, + wan_carrier: str | None | UndefinedType = Undefined, + wan_circuit_id: str | None | UndefinedType = Undefined, + connected_to_pathfinder: bool | UndefinedType = Undefined, + cv_pathfinder_internet_exit: CvPathfinderInternetExit | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L3InterfacesItem. + + + Subclass of AvdModel. + + Args: + profile: L3 interface profile name. Profile defined under `l3_interface_profiles`. + name: + Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. + For a + subinterface, the parent physical interface is automatically created. + description: + Interface description. + If not set a default description will be configured with '[[ + ]]'. + ip_address: Node IPv4 address/Mask or 'dhcp'. + dhcp_ip: + When the `ip_address` is `dhcp`, this optional field allows to indicate the expected + IPv4 address + (without mask) to be allocated on the interface if known. + This is not rendered in the configuration + but can be used for substitution of 'interface_ip' in the Access-list + set under `ipv4_acl_in` and + `ipv4_acl_out`. + public_ip: + Node IPv4 address (no mask). + + This is used to get the public IP (if known) when the device is behind + NAT. + This is only used for `wan_rr` routers (AutoVPN RRs and Pathfinders) to determine the Public IP + with the following preference: + `wan_route_servers.path_groups.interfaces.ip_address` + -> + `l3_interfaces.public_ip` + -> `l3_interfaces.ip_address` + + The determined Public IP is used + by WAN routers when peering with this interface. + encapsulation_dot1q_vlan: + For subinterfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + dhcp_accept_default_route: Accept a default route from DHCP if `ip_address` is set to `dhcp`. + enabled: Enable or Shutdown the interface. + speed: + Speed should be set in the format `` or `forced ` or `auto + `. + peer: The peer device name. Used for description and documentation. + peer_interface: The peer device interface. Used for description and documentation. + peer_ip: + The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true + and `ip` is an IP address. + bgp: + Enforce IPv4 BGP peering for the peer + + Subclass of AvdModel. + ipv4_acl_in: + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + Required + for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under + `wan_carriers`. + ipv4_acl_out: + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + static_routes: + Configure IPv4 static routes pointing to `peer_ip`. + + Subclass of AvdList with `StaticRoutesItem` + items. + qos_profile: QOS service profile. + wan_carrier: + The WAN carrier this interface is connected to. + This is used to infer the path-groups in which this + interface should be configured. + Unless the carrier is marked as 'trusted' under `wan_carriers`, + `ipv4_acl_in` is also required on all WAN interfaces. + wan_circuit_id: + The WAN circuit ID for this interface. + This is not rendered in the configuration but used for WAN + designs. + connected_to_pathfinder: For a WAN interface (`wan_carrier` is set), allow to disable the static tunnel towards Pathfinders. + cv_pathfinder_internet_exit: + PREVIEW: This key is in preview mode + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the interface in the final EOS configuration. + flow_tracking: + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + structured_config: + Custom structured config for the Ethernet interface. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): + """Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + L3Interfaces._item_type = L3InterfacesItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "downlink_pools": {"type": DownlinkPools}, + "id": {"type": int}, + "platform": {"type": str}, + "mac_address": {"type": str}, + "system_mac_address": {"type": str}, + "serial_number": {"type": str}, + "rack": {"type": str}, + "mgmt_ip": {"type": str}, + "mgmt_gateway": {"type": str}, + "ipv6_mgmt_ip": {"type": str}, + "ipv6_mgmt_gateway": {"type": str}, + "mgmt_interface": {"type": str}, + "link_tracking": {"type": LinkTracking}, + "lacp_port_id_range": {"type": LacpPortIdRange}, + "always_configure_ip_routing": {"type": bool, "default": False}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "uplink_type": {"type": str}, + "uplink_ipv4_pool": {"type": str}, + "uplink_interfaces": {"type": UplinkInterfaces}, + "uplink_switch_interfaces": {"type": UplinkSwitchInterfaces}, + "uplink_switches": {"type": UplinkSwitches}, + "uplink_interface_speed": {"type": str}, + "uplink_switch_interface_speed": {"type": str}, + "uplink_mtu": {"type": int}, + "max_uplink_switches": {"type": int}, + "max_parallel_uplinks": {"type": int, "default": 1}, + "uplink_bfd": {"type": bool, "default": False}, + "uplink_native_vlan": {"type": int}, + "uplink_ptp": {"type": UplinkPtp}, + "uplink_macsec": {"type": UplinkMacsec}, + "uplink_port_channel_id": {"type": int}, + "uplink_switch_port_channel_id": {"type": int}, + "uplink_structured_config": {"type": dict}, + "mlag_port_channel_structured_config": {"type": MlagPortChannelStructuredConfig}, + "mlag_peer_vlan_structured_config": {"type": MlagPeerVlanStructuredConfig}, + "mlag_peer_l3_vlan_structured_config": {"type": MlagPeerL3VlanStructuredConfig}, + "short_esi": {"type": str}, + "isis_system_id_prefix": {"type": str}, + "isis_maximum_paths": {"type": int}, + "is_type": {"type": str}, + "node_sid_base": {"type": int, "default": 0}, + "loopback_ipv4_pool": {"type": str}, + "loopback_ipv4_address": {"type": str}, + "vtep_loopback_ipv4_pool": {"type": str}, + "vtep_loopback_ipv4_address": {"type": str}, + "loopback_ipv4_offset": {"type": int, "default": 0}, + "loopback_ipv6_pool": {"type": str}, + "loopback_ipv6_offset": {"type": int, "default": 0}, + "vtep": {"type": bool}, + "vtep_loopback": {"type": str}, + "bgp_as": {"type": str}, + "bgp_defaults": {"type": BgpDefaults}, + "evpn_role": {"type": str}, + "evpn_route_servers": {"type": EvpnRouteServers}, + "evpn_services_l2_only": {"type": bool, "default": False}, + "filter": {"type": Filter}, + "igmp_snooping_enabled": {"type": bool}, + "evpn_gateway": {"type": EvpnGateway}, + "ipvpn_gateway": {"type": IpvpnGateway}, + "mlag": {"type": bool, "default": True}, + "mlag_dual_primary_detection": {"type": bool, "default": False}, + "mlag_ibgp_origin_incomplete": {"type": bool, "default": True}, + "mlag_interfaces": {"type": MlagInterfaces}, + "mlag_interfaces_speed": {"type": str}, + "mlag_peer_l3_vlan": {"type": int, "default": 4093}, + "mlag_peer_l3_ipv4_pool": {"type": str}, + "mlag_peer_vlan": {"type": int, "default": 4094}, + "mlag_peer_link_allowed_vlans": {"type": str}, + "mlag_peer_address_family": {"type": str, "default": "ipv4"}, + "mlag_peer_ipv4_pool": {"type": str}, + "mlag_peer_ipv6_pool": {"type": str}, + "mlag_port_channel_id": {"type": int}, + "mlag_domain_id": {"type": str}, + "spanning_tree_mode": {"type": str}, + "spanning_tree_priority": {"type": int, "default": 32768}, + "spanning_tree_root_super": {"type": bool, "default": False}, + "virtual_router_mac_address": {"type": str}, + "inband_mgmt_interface": {"type": str}, + "inband_mgmt_vlan": {"type": int, "default": 4092}, + "inband_mgmt_subnet": {"type": str}, + "inband_mgmt_ip": {"type": str}, + "inband_mgmt_gateway": {"type": str}, + "inband_mgmt_ipv6_address": {"type": str}, + "inband_mgmt_ipv6_subnet": {"type": str}, + "inband_mgmt_ipv6_gateway": {"type": str}, + "inband_mgmt_description": {"type": str, "default": "Inband Management"}, + "inband_mgmt_vlan_name": {"type": str, "default": "INBAND_MGMT"}, + "inband_mgmt_vrf": {"type": str, "default": "default"}, + "inband_mgmt_mtu": {"type": int, "default": 1500}, + "inband_ztp": {"type": bool, "default": False}, + "inband_ztp_lacp_fallback_delay": {"type": int, "default": 30}, + "mpls_overlay_role": {"type": str}, + "overlay_address_families": {"type": OverlayAddressFamilies}, + "mpls_route_reflectors": {"type": MplsRouteReflectors}, + "bgp_cluster_id": {"type": str}, + "ptp": {"type": Ptp}, + "wan_role": {"type": str}, + "cv_pathfinder_transit_mode": {"type": str}, + "cv_pathfinder_region": {"type": str}, + "cv_pathfinder_site": {"type": str}, + "wan_ha": {"type": WanHa}, + "dps_mss_ipv4": {"type": str, "default": "auto"}, + "l3_interfaces": {"type": L3Interfaces}, + "data_plane_cpu_allocation_max": {"type": int}, + "flow_tracker_type": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """The Node Name is used as "hostname".""" + downlink_pools: DownlinkPools + """ + IPv4 pools used for links to downlink switches. Set this on the parent switch. Cannot be combined + with `uplink_ipv4_pool` set on the downlink switch. + + Subclass of AvdList with `DownlinkPoolsItem` + items. + """ + id: int | None + """Unique identifier used for IP addressing and other algorithms.""" + platform: str | None + """Arista platform family.""" + mac_address: str | None + """Leverage to document management interface mac address.""" + system_mac_address: str | None + """ + System MAC Address in this following format: "xx:xx:xx:xx:xx:xx". + Set to the same MAC address as + available in "show version" on the device. + "system_mac_address" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + """ + serial_number: str | None + """ + Set to the Serial Number of the device. + Only used for documentation purpose in the fabric + documentation and part of the structured_config. + "serial_number" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + """ + rack: str | None + """Rack that the switch is located in (only used in snmp_settings location).""" + mgmt_ip: str | None + """Node management interface IPv4 address.""" + mgmt_gateway: str | None + """ + This key sets the management gateway for the device. It takes precedence over the global + `mgmt_gateway`. + """ + ipv6_mgmt_ip: str | None + """Node management interface IPv6 address.""" + ipv6_mgmt_gateway: str | None + """ + This key sets the ipv6 management gateway for the device. It takes precedence over the global + `ipv6_mgmt_gateway`. + """ + mgmt_interface: str | None + """ + Management Interface Name. + Default -> platform_management_interface -> mgmt_interface -> + "Management1". + """ + link_tracking: LinkTracking + """ + This configures the Link Tracking Group on a switch as well as adds the p2p-uplinks of the switch as + the upstream interfaces. + Useful in EVPN multhoming designs. + + + Subclass of AvdModel. + """ + lacp_port_id_range: LacpPortIdRange + """ + This will generate the "lacp port-id range", "begin" and "end" values based on node "id" and the + number of nodes in the "node_group". + Unique LACP port-id ranges are recommended for EVPN Multihoming + designs. + + + Subclass of AvdModel. + """ + always_configure_ip_routing: bool + """ + Force configuration of "ip routing" even on L2 devices. + Use this to retain behavior of AVD versions + below 4.0.0. + + Default value: `False` + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the root level of the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + """ + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None + """ + Override the default `uplink_type` set at the `node_type_key` level. + `uplink_type` must be "p2p" if + `vtep` or `underlay_router` is true for the `node_type_key` definition. + """ + uplink_ipv4_pool: str | None + """IPv4 subnet to use to connect to uplink switches.""" + uplink_interfaces: UplinkInterfaces + """ + Local uplink interfaces. + Each list item supports range syntax that can be expanded into a list of + interfaces. + If uplink_interfaces is not defined, platform-specific defaults (defined under + default_interfaces) will be used instead. + Please note that default_interfaces are not defined by + default, you should define these yourself. + + + Subclass of AvdList with `str` items. + """ + uplink_switch_interfaces: UplinkSwitchInterfaces + """ + Interfaces located on uplink switches. + + Subclass of AvdList with `str` items. + """ + uplink_switches: UplinkSwitches + """Subclass of AvdList with `str` items.""" + uplink_interface_speed: str | None + """ + Set point-to-Point interface speed and will apply to uplink interfaces on both ends. + (Uplink switch + interface speed can be overridden with `uplink_switch_interface_speed`). + Speed should be set in the + format `` or `forced ` or `auto `. + """ + uplink_switch_interface_speed: str | None + """ + 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: int | None + """Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting.""" + max_uplink_switches: int | None + """ + 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: 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 + """ + Enable bfd on uplink interfaces. + + Default value: `False` + """ + uplink_native_vlan: int | None + """ + 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: UplinkPtp + """ + Enable PTP on all infrastructure links. + + Subclass of AvdModel. + """ + uplink_macsec: UplinkMacsec + """ + Enable MacSec on all uplinks. + + Subclass of AvdModel. + """ + uplink_port_channel_id: int | None + """ + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink Port-channel + ID will be set to the number of the lowest member interface defined under `uplink_interfaces`. + For + example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ Eth11/1, Eth22/1 ] -> ID 111 + For + MLAG port-channels ID will be based on the lowest member interface on the first MLAG switch. + This + option overrides the default behavior and statically sets the local Port-channel ID. + Note! Make sure + the ID is unique and does not overlap with autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between 1 and 2000 and both MLAG switches must have the same + value. + """ + uplink_switch_port_channel_id: int | None + """ + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink switch Port- + channel ID will be set to the number of the first interface defined under + `uplink_switch_interfaces`. + For example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ + Eth11/1, Eth22/1 ] -> ID 111 + For MLAG port-channels ID will be based on the lowest member interface + on the first MLAG switch. + This option overrides the default behavior and statically sets the Port- + channel ID on the uplink switch. + Note! Make sure the ID is unique and does not overlap with + autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between + 1 and 2000 and both MLAG switches must have the same value. + """ + uplink_structured_config: dict + """ + Custom structured config applied to "uplink_interfaces", and "uplink_switch_interfaces". + When + uplink_type == "p2p", custom structured config added under ethernet_interfaces.[name=] + for eos_cli_config_gen overrides the settings on the ethernet interface level. + When uplink_type == + "port-channel", custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen overrides the settings on the port-channel interface level. + "uplink_structured_config" is applied after "structured_config", so it can override + "structured_config" defined on node-level. + Note! The content of this dictionary is _not_ validated + by the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + """ + mlag_port_channel_structured_config: MlagPortChannelStructuredConfig + """ + Custom structured config applied to MLAG peer link port-channel id. + Added under + port_channel_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the + port-channel interface level. + "mlag_port_channel_structured_config" is applied after + "structured_config", so it can override "structured_config" defined on node-level. + + + Subclass of + AvdModel. + """ + mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig + """ + Custom structured config applied to MLAG Peer Link (control link) SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_vlan_structured_config" is applied after "structured_config", so it can + override "structured_config" defined on node-level. + + + Subclass of AvdModel. + """ + mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig + """ + Custom structured config applied to MLAG underlay L3 peering SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_l3_vlan_structured_config" is applied after "structured_config", so it + can override "structured_config" defined on node-level. + + + Subclass of AvdModel. + """ + short_esi: str | None + """ + short_esi only valid for l2leaf devices using port-channel uplink. + Setting short_esi to "auto" + generates the short_esi automatically using a hash of configuration elements. + < 0000:0000:0000 | + auto >. + """ + isis_system_id_prefix: str | None + """(4.4 hexadecimal).""" + isis_maximum_paths: int | None + """Number of path to configure in ECMP for ISIS.""" + is_type: Literal["level-1-2", "level-1", "level-2"] | None + """Overrides `isis_default_is_type`.""" + node_sid_base: int + """ + Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID. + + Default value: `0` + """ + loopback_ipv4_pool: str | None + """IPv4 subnet for Loopback0 allocation.""" + loopback_ipv4_address: str | None + """ + IPv4 address without mask for Loopback0. + When set, it takes precedence over `loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not catch duplicates. + """ + vtep_loopback_ipv4_pool: str | None + """IPv4 subnet for VTEP-Loopback allocation.""" + vtep_loopback_ipv4_address: str | None + """ + IPv4 address without mask for VTEP-Loopback. + When set, it takes precedence over + `vtep_loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not + catch duplicates. + """ + loopback_ipv4_offset: int + """ + Offset all assigned loopback IP addresses. + Required when the < loopback_ipv4_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid over-lapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv4_offset: < total # spine switches > or vice versa. + + Default value: `0` + """ + loopback_ipv6_pool: str | None + """IPv6 subnet for Loopback0 allocation.""" + loopback_ipv6_offset: int + """ + Offset all assigned loopback IPv6 addresses. + Required when the < loopback_ipv6_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid overlapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv6_offset: < total # spine switches > or vice versa. + + Default value: `0` + """ + vtep: bool | None + """ + Node is configured as a VTEP when applicable based on 'overlay_routing_protocol'. + Overrides VTEP + setting inherited from node_type_keys. + """ + vtep_loopback: str | None + """Set VXLAN source interface.""" + bgp_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + Required with eBGP. + """ + bgp_defaults: BgpDefaults + """ + List of EOS commands to apply to BGP daemon. + + Subclass of AvdList with `str` items. + """ + evpn_role: Literal["client", "server", "none"] | None + """ + Acting role in EVPN control plane. + Default is set in node_type definition from node_type_keys. + """ + evpn_route_servers: EvpnRouteServers + """ + List of nodes acting as EVPN Route-Servers / Route-Reflectors. + + Subclass of AvdList with `str` + items. + """ + evpn_services_l2_only: bool + """ + Possibility to prevent configuration of Tenant VRFs and SVIs. + Override node definition + "network_services_l3" from node_type_keys. + This allows support for centralized routing. + + Default value: `False` + """ + filter: Filter + """ + Filter L3 and L2 network services based on tenant and tags (and operation filter). + If filter is not + defined it will default to all. + + + Subclass of AvdModel. + """ + igmp_snooping_enabled: bool | None + """Activate or deactivate IGMP snooping on device level.""" + evpn_gateway: EvpnGateway + """ + Node is acting as EVPN Multi-Domain Gateway. + New BGP peer-group is generated between EVPN GWs in + different domains or between GWs and Route Servers. + Name can be changed under + "bgp_peer_groups.evpn_overlay_core" variable. + L3 rechability for different EVPN GWs must be already + in place, it is recommended to use DCI & L3 Edge if Route Servers and GWs are not defined under the + same Ansible inventory. + + + Subclass of AvdModel. + """ + ipvpn_gateway: IpvpnGateway + """ + Node is acting as IP-VPN Gateway for EVPN to MPLS-IP-VPN Interworking. The BGP peer group used for + this is "bgp_peer_groups.ipvpn_gateway_peers". + L3 Reachability is required for this to work, the + preferred method to establish underlay connectivity is to use core_interfaces. + + + Subclass of + AvdModel. + """ + mlag: bool + """ + Enable / Disable auto MLAG, when two nodes are defined in node group. + + Default value: `True` + """ + mlag_dual_primary_detection: bool + """ + Enable / Disable MLAG dual primary detection. + + Default value: `False` + """ + mlag_ibgp_origin_incomplete: bool + """ + Set origin of routes received from MLAG iBGP peer to incomplete. + The purpose is to optimize routing + for leaf loopbacks from spine perspective and + avoid suboptimal routing via peerlink for control + plane traffic. + + Default value: `True` + """ + mlag_interfaces: MlagInterfaces + """ + Each list item supports range syntax that can be expanded into a list of interfaces. + Required when + MLAG leafs are present in the topology. + + + Subclass of AvdList with `str` items. + """ + mlag_interfaces_speed: str | None + """ + Set MLAG interface speed. + Speed should be set in the format `` or `forced + ` or `auto `. + """ + mlag_peer_l3_vlan: int + """ + Underlay L3 peering SVI interface id. + If set to 0 or the same vlan as mlag_peer_vlan, the + mlag_peer_vlan will be used for L3 peering. + + Default value: `4093` + """ + mlag_peer_l3_ipv4_pool: str | None + """ + IP address pool used for MLAG underlay L3 peering. IP is derived from the node id. + Required when + MLAG leafs present in topology and they are using a separate L3 peering VLAN. + """ + mlag_peer_vlan: int + """ + MLAG Peer Link (control link) SVI interface id. + + Default value: `4094` + """ + mlag_peer_link_allowed_vlans: str | None + mlag_peer_address_family: Literal["ipv4", "ipv6"] + """ + IP address family used to establish MLAG Peer Link (control link). + `ipv6` requires EOS version + 4.31.1F or higher. + Note: `ipv6` is not supported in combination with a common MLAG peer link VLAN + (ex. `mlag_peer_l3_vlan` set to 4094). + + Default value: `"ipv4"` + """ + mlag_peer_ipv4_pool: str | None + """ + IPv4 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv4` (default). + """ + mlag_peer_ipv6_pool: str | None + """ + IPv6 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv6`. + """ + mlag_port_channel_id: int | None + """ + If not set, the mlag port-channel id is generated based on the digits of the first interface present + in 'mlag_interfaces'. + Valid port-channel id numbers are < 1-2000 > for EOS < 4.25.0F and < 1 - + 999999 > for EOS >= 4.25.0F. + """ + mlag_domain_id: str | None + """MLAG Domain ID. If not set the node group name (Set with "group" key) will be used.""" + spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None + spanning_tree_priority: int + """ + Spanning-tree priority configured for the selected mode. + For `rapid-pvst` the priority can also be + set per VLAN under network services. + + Default value: `32768` + """ + spanning_tree_root_super: bool + """Default value: `False`""" + virtual_router_mac_address: str | None + """Virtual router mac address for anycast gateway.""" + inband_mgmt_interface: str | None + """ + Pointer to interface used for inband management. + All configuration must be done using other data + models like network services or structured_config. + 'inband_mgmt_interface' is only used to refer to + this interface as source in various management protocol settings (future feature). + + On L2 switches, + this defaults to Vlan if either 'inband_mgmt_subnet' or 'inband_mgmt_ip' is set. + """ + inband_mgmt_vlan: int + """ + VLAN number used for inband management on L2 switches (switches using port-channel trunks as + uplinks). + When using 'inband_mgmt_subnet' the VLAN and SVIs will be created automatically on this + switch as well as all 'uplink_switches'. + When using 'inband_mgmt_ip' the VLAN and SVI will only be + created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be + created using network services data models. + + Default value: `4092` + """ + inband_mgmt_subnet: str | None + """ + Optional IP subnet assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ip virtual-router" and host-route injection based on + ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + + 3 + + GW on l2leafs : + 1 + Assign range larger than total l2leafs + 5 + Setting is ignored if 'inband_mgmt_ip' is set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + """ + inband_mgmt_ip: str | None + """ + IP address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_subnet', hence all behavior of 'inband_mgmt_subnet' is removed. + + If this is set the + VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN and SVI on + the parent switches must be created using network services data models. + + This setting is applicable + to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_gateway: str | None + """ + Default gateway configured in the 'inband_mgmt_vrf' when using 'inband_mgmt_ip'. Otherwise gateway + is derived from 'inband_mgmt_subnet' if set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_address: str | None + """ + IPv6 address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_ipv6_subnet', hence the configuration of 'inband_mgmt_ipv6_subnet' is ignored. + + If this + is set the VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN + and SVI on the parent switches must be created using network services data models. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_subnet: str | None + """ + Optional IPv6 prefix assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ipv6 virtual-router" and host-route injection based + on ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN + extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + 3 + + GW on l2leafs : + 1 + Assign range larger than + total l2leafs + 5 + + Setting is ignored if 'inband_mgmt_ipv6_address' is set. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_gateway: str | None + """ + Default gateway configured in the 'inband_mgmt_vrf'. + Used when `inband_mgmt_ipv6_address` is set. + Ignored when 'inband_mgmt_ipv6_subnet' is set (first IP in subnet used as gateway). + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_description: str + """ + Description configured on the Inband Management SVI. + + This setting is only applied on the devices + where it is set, it does not automatically affect any parent/child devices configuration, so it must + be set on each applicable node/node-group/node-type as needed. + + Default value: `"Inband Management"` + """ + inband_mgmt_vlan_name: str + """ + Name configured on the Inband Management VLAN. + This setting is only applied on the devices where it + is set, it does not automatically affect any parent/child devices configuration, so it must be set + on each applicable node/node-group/node-type as needed. + + Default value: `"INBAND_MGMT"` + """ + inband_mgmt_vrf: str + """ + VRF configured on the Inband Management Interface. + The VRF is created if not already created by + other means. + This setting is only applied on the devices where it is set, it does not automatically + affect any parent/child devices configuration, so it must be set on each applicable node/node- + group/node-type as needed. + + Default value: `"default"` + """ + inband_mgmt_mtu: int + """ + MTU configured on the Inband Management Interface. + This setting is only applied on the devices where + it is set, it does not automatically affect any parent/child devices configuration, so it must be + set on each applicable node/node-group/node-type as needed. + + Default value: `1500` + """ + inband_ztp: bool + """ + Enable to configure upstream device with proper configuration to allow downstream devices to be + Zero-Touch-Provisioned over the uplink interfaces. + For L2 devices this setting also requires that + the `inband_mgmt_vlan` is set for the node. + + PREVIEW: Support for L3 devices is marked as "preview", + meaning the data models or generated configuration can change at any time. + + Default value: `False` + """ + inband_ztp_lacp_fallback_delay: int + """ + Set the LACP fallback timeout of the upstream device's port-channel towards the downstream inband + ZTP node. + This setting also requires that `inband_ztp` is set for the node. + + Default value: `30` + """ + mpls_overlay_role: Literal["client", "server", "none"] | None + """ + Set the default mpls overlay role. + Acting role in overlay control plane. + """ + overlay_address_families: OverlayAddressFamilies + """ + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + """ + mpls_route_reflectors: MplsRouteReflectors + """ + List of inventory hostname acting as MPLS route-reflectors. + + Subclass of AvdList with `str` items. + """ + bgp_cluster_id: str | None + """Set BGP cluster id.""" + ptp: Ptp + """Subclass of AvdModel.""" + wan_role: Literal["client", "server"] | None + """ + Override the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + """ + cv_pathfinder_transit_mode: Literal["region", "zone"] | None + """ + Configure the transit mode for a WAN client for CV Pathfinder designs + only when the `wan_mode` root + key is set to `cv_pathfinder`. + + 'zone' is currently not supported. + """ + cv_pathfinder_region: str | None + """ + The CV Pathfinder region name. + This key is required for WAN routers but optional for pathfinders. + The region name must be defined under 'cv_pathfinder_regions'. + """ + cv_pathfinder_site: str | None + """ + The CV Pathfinder site name. + This key is required for WAN routers but optional for pathfinders. + For + WAN routers and pathfinders with `cv_pathfinder_region`, the site name must be defined for the + relevant region under 'cv_pathfinder_regions'. + For pathfinders without `cv_pathfinder_region` set, + the site must be defined under `cv_pathfinder_global_sites`. + """ + wan_ha: WanHa + """ + PREVIEW: This key is currently not supported + + The key is supported only if `wan_mode` == `cv- + pathfinder`. + AutoVPN support is still to be determined. + + Maximum 2 devices supported by group for + HA. + + Subclass of AvdModel. + """ + dps_mss_ipv4: str + """ + IPv4 MSS value configured under "router path-selection" on WAN Devices. + + Default value: `"auto"` + """ + l3_interfaces: L3Interfaces + """ + L3 Interfaces to configure on the node. + Used to define the node for WAN interfaces when + `wan_carrier` is set. + + Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is + `name` (`str`). + """ + data_plane_cpu_allocation_max: int | None + """ + Set the maximum number of CPU used for the data plane. + This setting is useful on virtual Route + Reflectors and Pathfinders where more CPU cores should be allocated for control plane. + """ + flow_tracker_type: Literal["sampled", "hardware"] | None + """ + Set the flow tracker type. + Override the `default_flow_tracker_type`` set at the `node_type_key` + level. + `default_flow_tracker_type` default value is `sampled`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + downlink_pools: DownlinkPools | UndefinedType = Undefined, + id: int | None | UndefinedType = Undefined, + platform: str | None | UndefinedType = Undefined, + mac_address: str | None | UndefinedType = Undefined, + system_mac_address: str | None | UndefinedType = Undefined, + serial_number: str | None | UndefinedType = Undefined, + rack: str | None | UndefinedType = Undefined, + mgmt_ip: str | None | UndefinedType = Undefined, + mgmt_gateway: str | None | UndefinedType = Undefined, + ipv6_mgmt_ip: str | None | UndefinedType = Undefined, + ipv6_mgmt_gateway: str | None | UndefinedType = Undefined, + mgmt_interface: str | None | UndefinedType = Undefined, + link_tracking: LinkTracking | UndefinedType = Undefined, + lacp_port_id_range: LacpPortIdRange | UndefinedType = Undefined, + always_configure_ip_routing: bool | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None | UndefinedType = Undefined, + uplink_ipv4_pool: str | None | UndefinedType = Undefined, + uplink_interfaces: UplinkInterfaces | UndefinedType = Undefined, + uplink_switch_interfaces: UplinkSwitchInterfaces | UndefinedType = Undefined, + uplink_switches: UplinkSwitches | UndefinedType = Undefined, + uplink_interface_speed: str | None | UndefinedType = Undefined, + 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 | UndefinedType = Undefined, + uplink_bfd: bool | UndefinedType = Undefined, + uplink_native_vlan: int | None | UndefinedType = Undefined, + uplink_ptp: UplinkPtp | UndefinedType = Undefined, + uplink_macsec: UplinkMacsec | UndefinedType = Undefined, + uplink_port_channel_id: int | None | UndefinedType = Undefined, + uplink_switch_port_channel_id: int | None | UndefinedType = Undefined, + uplink_structured_config: dict | UndefinedType = Undefined, + mlag_port_channel_structured_config: MlagPortChannelStructuredConfig | UndefinedType = Undefined, + mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig | UndefinedType = Undefined, + mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig | UndefinedType = Undefined, + short_esi: str | None | UndefinedType = Undefined, + isis_system_id_prefix: str | None | UndefinedType = Undefined, + isis_maximum_paths: int | None | UndefinedType = Undefined, + is_type: Literal["level-1-2", "level-1", "level-2"] | None | UndefinedType = Undefined, + node_sid_base: int | UndefinedType = Undefined, + loopback_ipv4_pool: str | None | UndefinedType = Undefined, + loopback_ipv4_address: str | None | UndefinedType = Undefined, + vtep_loopback_ipv4_pool: str | None | UndefinedType = Undefined, + vtep_loopback_ipv4_address: str | None | UndefinedType = Undefined, + loopback_ipv4_offset: int | UndefinedType = Undefined, + loopback_ipv6_pool: str | None | UndefinedType = Undefined, + loopback_ipv6_offset: int | UndefinedType = Undefined, + vtep: bool | None | UndefinedType = Undefined, + vtep_loopback: str | None | UndefinedType = Undefined, + bgp_as: str | None | UndefinedType = Undefined, + bgp_defaults: BgpDefaults | UndefinedType = Undefined, + evpn_role: Literal["client", "server", "none"] | None | UndefinedType = Undefined, + evpn_route_servers: EvpnRouteServers | UndefinedType = Undefined, + evpn_services_l2_only: bool | UndefinedType = Undefined, + filter: Filter | UndefinedType = Undefined, + igmp_snooping_enabled: bool | None | UndefinedType = Undefined, + evpn_gateway: EvpnGateway | UndefinedType = Undefined, + ipvpn_gateway: IpvpnGateway | UndefinedType = Undefined, + mlag: bool | UndefinedType = Undefined, + mlag_dual_primary_detection: bool | UndefinedType = Undefined, + mlag_ibgp_origin_incomplete: bool | UndefinedType = Undefined, + mlag_interfaces: MlagInterfaces | UndefinedType = Undefined, + mlag_interfaces_speed: str | None | UndefinedType = Undefined, + mlag_peer_l3_vlan: int | UndefinedType = Undefined, + mlag_peer_l3_ipv4_pool: str | None | UndefinedType = Undefined, + mlag_peer_vlan: int | UndefinedType = Undefined, + mlag_peer_link_allowed_vlans: str | None | UndefinedType = Undefined, + mlag_peer_address_family: Literal["ipv4", "ipv6"] | UndefinedType = Undefined, + mlag_peer_ipv4_pool: str | None | UndefinedType = Undefined, + mlag_peer_ipv6_pool: str | None | UndefinedType = Undefined, + mlag_port_channel_id: int | None | UndefinedType = Undefined, + mlag_domain_id: str | None | UndefinedType = Undefined, + spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None | UndefinedType = Undefined, + spanning_tree_priority: int | UndefinedType = Undefined, + spanning_tree_root_super: bool | UndefinedType = Undefined, + virtual_router_mac_address: str | None | UndefinedType = Undefined, + inband_mgmt_interface: str | None | UndefinedType = Undefined, + inband_mgmt_vlan: int | UndefinedType = Undefined, + inband_mgmt_subnet: str | None | UndefinedType = Undefined, + inband_mgmt_ip: str | None | UndefinedType = Undefined, + inband_mgmt_gateway: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_address: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_subnet: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_gateway: str | None | UndefinedType = Undefined, + inband_mgmt_description: str | UndefinedType = Undefined, + inband_mgmt_vlan_name: str | UndefinedType = Undefined, + inband_mgmt_vrf: str | UndefinedType = Undefined, + inband_mgmt_mtu: int | UndefinedType = Undefined, + inband_ztp: bool | UndefinedType = Undefined, + inband_ztp_lacp_fallback_delay: int | UndefinedType = Undefined, + mpls_overlay_role: Literal["client", "server", "none"] | None | UndefinedType = Undefined, + overlay_address_families: OverlayAddressFamilies | UndefinedType = Undefined, + mpls_route_reflectors: MplsRouteReflectors | UndefinedType = Undefined, + bgp_cluster_id: str | None | UndefinedType = Undefined, + ptp: Ptp | UndefinedType = Undefined, + wan_role: Literal["client", "server"] | None | UndefinedType = Undefined, + cv_pathfinder_transit_mode: Literal["region", "zone"] | None | UndefinedType = Undefined, + cv_pathfinder_region: str | None | UndefinedType = Undefined, + cv_pathfinder_site: str | None | UndefinedType = Undefined, + wan_ha: WanHa | UndefinedType = Undefined, + dps_mss_ipv4: str | UndefinedType = Undefined, + l3_interfaces: L3Interfaces | UndefinedType = Undefined, + data_plane_cpu_allocation_max: int | None | UndefinedType = Undefined, + flow_tracker_type: Literal["sampled", "hardware"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NodesItem. + + + Subclass of AvdModel. + + Args: + name: The Node Name is used as "hostname". + downlink_pools: + IPv4 pools used for links to downlink switches. Set this on the parent switch. Cannot be combined + with `uplink_ipv4_pool` set on the downlink switch. + + Subclass of AvdList with `DownlinkPoolsItem` + items. + id: Unique identifier used for IP addressing and other algorithms. + platform: Arista platform family. + mac_address: Leverage to document management interface mac address. + system_mac_address: + System MAC Address in this following format: "xx:xx:xx:xx:xx:xx". + Set to the same MAC address as + available in "show version" on the device. + "system_mac_address" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + serial_number: + Set to the Serial Number of the device. + Only used for documentation purpose in the fabric + documentation and part of the structured_config. + "serial_number" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + rack: Rack that the switch is located in (only used in snmp_settings location). + mgmt_ip: Node management interface IPv4 address. + mgmt_gateway: + This key sets the management gateway for the device. It takes precedence over the global + `mgmt_gateway`. + ipv6_mgmt_ip: Node management interface IPv6 address. + ipv6_mgmt_gateway: + This key sets the ipv6 management gateway for the device. It takes precedence over the global + `ipv6_mgmt_gateway`. + mgmt_interface: + Management Interface Name. + Default -> platform_management_interface -> mgmt_interface -> + "Management1". + link_tracking: + This configures the Link Tracking Group on a switch as well as adds the p2p-uplinks of the switch as + the upstream interfaces. + Useful in EVPN multhoming designs. + + + Subclass of AvdModel. + lacp_port_id_range: + This will generate the "lacp port-id range", "begin" and "end" values based on node "id" and the + number of nodes in the "node_group". + Unique LACP port-id ranges are recommended for EVPN Multihoming + designs. + + + Subclass of AvdModel. + always_configure_ip_routing: + Force configuration of "ip routing" even on L2 devices. + Use this to retain behavior of AVD versions + below 4.0.0. + raw_eos_cli: EOS CLI rendered directly on the root level of the final EOS configuration. + structured_config: + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + uplink_type: + Override the default `uplink_type` set at the `node_type_key` level. + `uplink_type` must be "p2p" if + `vtep` or `underlay_router` is true for the `node_type_key` definition. + uplink_ipv4_pool: IPv4 subnet to use to connect to uplink switches. + uplink_interfaces: + Local uplink interfaces. + Each list item supports range syntax that can be expanded into a list of + interfaces. + If uplink_interfaces is not defined, platform-specific defaults (defined under + default_interfaces) will be used instead. + Please note that default_interfaces are not defined by + default, you should define these yourself. + + + Subclass of AvdList with `str` items. + uplink_switch_interfaces: + Interfaces located on uplink switches. + + Subclass of AvdList with `str` items. + uplink_switches: Subclass of AvdList with `str` items. + uplink_interface_speed: + Set point-to-Point interface speed and will apply to uplink interfaces on both ends. + (Uplink switch + interface speed can be overridden with `uplink_switch_interface_speed`). + Speed should be set in the + format `` or `forced ` or `auto `. + uplink_switch_interface_speed: + 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: Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting. + max_uplink_switches: + 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: + 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: Enable bfd on uplink interfaces. + uplink_native_vlan: + 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: + Enable PTP on all infrastructure links. + + Subclass of AvdModel. + uplink_macsec: + Enable MacSec on all uplinks. + + Subclass of AvdModel. + uplink_port_channel_id: + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink Port-channel + ID will be set to the number of the lowest member interface defined under `uplink_interfaces`. + For + example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ Eth11/1, Eth22/1 ] -> ID 111 + For + MLAG port-channels ID will be based on the lowest member interface on the first MLAG switch. + This + option overrides the default behavior and statically sets the local Port-channel ID. + Note! Make sure + the ID is unique and does not overlap with autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between 1 and 2000 and both MLAG switches must have the same + value. + uplink_switch_port_channel_id: + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink switch Port- + channel ID will be set to the number of the first interface defined under + `uplink_switch_interfaces`. + For example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ + Eth11/1, Eth22/1 ] -> ID 111 + For MLAG port-channels ID will be based on the lowest member interface + on the first MLAG switch. + This option overrides the default behavior and statically sets the Port- + channel ID on the uplink switch. + Note! Make sure the ID is unique and does not overlap with + autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between + 1 and 2000 and both MLAG switches must have the same value. + uplink_structured_config: + Custom structured config applied to "uplink_interfaces", and "uplink_switch_interfaces". + When + uplink_type == "p2p", custom structured config added under ethernet_interfaces.[name=] + for eos_cli_config_gen overrides the settings on the ethernet interface level. + When uplink_type == + "port-channel", custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen overrides the settings on the port-channel interface level. + "uplink_structured_config" is applied after "structured_config", so it can override + "structured_config" defined on node-level. + Note! The content of this dictionary is _not_ validated + by the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + mlag_port_channel_structured_config: + Custom structured config applied to MLAG peer link port-channel id. + Added under + port_channel_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the + port-channel interface level. + "mlag_port_channel_structured_config" is applied after + "structured_config", so it can override "structured_config" defined on node-level. + + + Subclass of + AvdModel. + mlag_peer_vlan_structured_config: + Custom structured config applied to MLAG Peer Link (control link) SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_vlan_structured_config" is applied after "structured_config", so it can + override "structured_config" defined on node-level. + + + Subclass of AvdModel. + mlag_peer_l3_vlan_structured_config: + Custom structured config applied to MLAG underlay L3 peering SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_l3_vlan_structured_config" is applied after "structured_config", so it + can override "structured_config" defined on node-level. + + + Subclass of AvdModel. + short_esi: + short_esi only valid for l2leaf devices using port-channel uplink. + Setting short_esi to "auto" + generates the short_esi automatically using a hash of configuration elements. + < 0000:0000:0000 | + auto >. + isis_system_id_prefix: (4.4 hexadecimal). + isis_maximum_paths: Number of path to configure in ECMP for ISIS. + is_type: Overrides `isis_default_is_type`. + node_sid_base: Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID. + loopback_ipv4_pool: IPv4 subnet for Loopback0 allocation. + loopback_ipv4_address: + IPv4 address without mask for Loopback0. + When set, it takes precedence over `loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not catch duplicates. + vtep_loopback_ipv4_pool: IPv4 subnet for VTEP-Loopback allocation. + vtep_loopback_ipv4_address: + IPv4 address without mask for VTEP-Loopback. + When set, it takes precedence over + `vtep_loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not + catch duplicates. + loopback_ipv4_offset: + Offset all assigned loopback IP addresses. + Required when the < loopback_ipv4_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid over-lapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv4_offset: < total # spine switches > or vice versa. + loopback_ipv6_pool: IPv6 subnet for Loopback0 allocation. + loopback_ipv6_offset: + Offset all assigned loopback IPv6 addresses. + Required when the < loopback_ipv6_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid overlapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv6_offset: < total # spine switches > or vice versa. + vtep: + Node is configured as a VTEP when applicable based on 'overlay_routing_protocol'. + Overrides VTEP + setting inherited from node_type_keys. + vtep_loopback: Set VXLAN source interface. + bgp_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + Required with eBGP. + bgp_defaults: + List of EOS commands to apply to BGP daemon. + + Subclass of AvdList with `str` items. + evpn_role: + Acting role in EVPN control plane. + Default is set in node_type definition from node_type_keys. + evpn_route_servers: + List of nodes acting as EVPN Route-Servers / Route-Reflectors. + + Subclass of AvdList with `str` + items. + evpn_services_l2_only: + Possibility to prevent configuration of Tenant VRFs and SVIs. + Override node definition + "network_services_l3" from node_type_keys. + This allows support for centralized routing. + filter: + Filter L3 and L2 network services based on tenant and tags (and operation filter). + If filter is not + defined it will default to all. + + + Subclass of AvdModel. + igmp_snooping_enabled: Activate or deactivate IGMP snooping on device level. + evpn_gateway: + Node is acting as EVPN Multi-Domain Gateway. + New BGP peer-group is generated between EVPN GWs in + different domains or between GWs and Route Servers. + Name can be changed under + "bgp_peer_groups.evpn_overlay_core" variable. + L3 rechability for different EVPN GWs must be already + in place, it is recommended to use DCI & L3 Edge if Route Servers and GWs are not defined under the + same Ansible inventory. + + + Subclass of AvdModel. + ipvpn_gateway: + Node is acting as IP-VPN Gateway for EVPN to MPLS-IP-VPN Interworking. The BGP peer group used for + this is "bgp_peer_groups.ipvpn_gateway_peers". + L3 Reachability is required for this to work, the + preferred method to establish underlay connectivity is to use core_interfaces. + + + Subclass of + AvdModel. + mlag: Enable / Disable auto MLAG, when two nodes are defined in node group. + mlag_dual_primary_detection: Enable / Disable MLAG dual primary detection. + mlag_ibgp_origin_incomplete: + Set origin of routes received from MLAG iBGP peer to incomplete. + The purpose is to optimize routing + for leaf loopbacks from spine perspective and + avoid suboptimal routing via peerlink for control + plane traffic. + mlag_interfaces: + Each list item supports range syntax that can be expanded into a list of interfaces. + Required when + MLAG leafs are present in the topology. + + + Subclass of AvdList with `str` items. + mlag_interfaces_speed: + Set MLAG interface speed. + Speed should be set in the format `` or `forced + ` or `auto `. + mlag_peer_l3_vlan: + Underlay L3 peering SVI interface id. + If set to 0 or the same vlan as mlag_peer_vlan, the + mlag_peer_vlan will be used for L3 peering. + mlag_peer_l3_ipv4_pool: + IP address pool used for MLAG underlay L3 peering. IP is derived from the node id. + Required when + MLAG leafs present in topology and they are using a separate L3 peering VLAN. + mlag_peer_vlan: MLAG Peer Link (control link) SVI interface id. + mlag_peer_link_allowed_vlans: mlag_peer_link_allowed_vlans + mlag_peer_address_family: + IP address family used to establish MLAG Peer Link (control link). + `ipv6` requires EOS version + 4.31.1F or higher. + Note: `ipv6` is not supported in combination with a common MLAG peer link VLAN + (ex. `mlag_peer_l3_vlan` set to 4094). + mlag_peer_ipv4_pool: + IPv4 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv4` (default). + mlag_peer_ipv6_pool: + IPv6 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv6`. + mlag_port_channel_id: + If not set, the mlag port-channel id is generated based on the digits of the first interface present + in 'mlag_interfaces'. + Valid port-channel id numbers are < 1-2000 > for EOS < 4.25.0F and < 1 - + 999999 > for EOS >= 4.25.0F. + mlag_domain_id: MLAG Domain ID. If not set the node group name (Set with "group" key) will be used. + spanning_tree_mode: spanning_tree_mode + spanning_tree_priority: + Spanning-tree priority configured for the selected mode. + For `rapid-pvst` the priority can also be + set per VLAN under network services. + spanning_tree_root_super: spanning_tree_root_super + virtual_router_mac_address: Virtual router mac address for anycast gateway. + inband_mgmt_interface: + Pointer to interface used for inband management. + All configuration must be done using other data + models like network services or structured_config. + 'inband_mgmt_interface' is only used to refer to + this interface as source in various management protocol settings (future feature). + + On L2 switches, + this defaults to Vlan if either 'inband_mgmt_subnet' or 'inband_mgmt_ip' is set. + inband_mgmt_vlan: + VLAN number used for inband management on L2 switches (switches using port-channel trunks as + uplinks). + When using 'inband_mgmt_subnet' the VLAN and SVIs will be created automatically on this + switch as well as all 'uplink_switches'. + When using 'inband_mgmt_ip' the VLAN and SVI will only be + created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be + created using network services data models. + inband_mgmt_subnet: + Optional IP subnet assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ip virtual-router" and host-route injection based on + ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + + 3 + + GW on l2leafs : + 1 + Assign range larger than total l2leafs + 5 + Setting is ignored if 'inband_mgmt_ip' is set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + inband_mgmt_ip: + IP address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_subnet', hence all behavior of 'inband_mgmt_subnet' is removed. + + If this is set the + VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN and SVI on + the parent switches must be created using network services data models. + + This setting is applicable + to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_gateway: + Default gateway configured in the 'inband_mgmt_vrf' when using 'inband_mgmt_ip'. Otherwise gateway + is derived from 'inband_mgmt_subnet' if set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + inband_mgmt_ipv6_address: + IPv6 address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_ipv6_subnet', hence the configuration of 'inband_mgmt_ipv6_subnet' is ignored. + + If this + is set the VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN + and SVI on the parent switches must be created using network services data models. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_ipv6_subnet: + Optional IPv6 prefix assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ipv6 virtual-router" and host-route injection based + on ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN + extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + 3 + + GW on l2leafs : + 1 + Assign range larger than + total l2leafs + 5 + + Setting is ignored if 'inband_mgmt_ipv6_address' is set. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_ipv6_gateway: + Default gateway configured in the 'inband_mgmt_vrf'. + Used when `inband_mgmt_ipv6_address` is set. + Ignored when 'inband_mgmt_ipv6_subnet' is set (first IP in subnet used as gateway). + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_description: + Description configured on the Inband Management SVI. + + This setting is only applied on the devices + where it is set, it does not automatically affect any parent/child devices configuration, so it must + be set on each applicable node/node-group/node-type as needed. + inband_mgmt_vlan_name: + Name configured on the Inband Management VLAN. + This setting is only applied on the devices where it + is set, it does not automatically affect any parent/child devices configuration, so it must be set + on each applicable node/node-group/node-type as needed. + inband_mgmt_vrf: + VRF configured on the Inband Management Interface. + The VRF is created if not already created by + other means. + This setting is only applied on the devices where it is set, it does not automatically + affect any parent/child devices configuration, so it must be set on each applicable node/node- + group/node-type as needed. + inband_mgmt_mtu: + MTU configured on the Inband Management Interface. + This setting is only applied on the devices where + it is set, it does not automatically affect any parent/child devices configuration, so it must be + set on each applicable node/node-group/node-type as needed. + inband_ztp: + Enable to configure upstream device with proper configuration to allow downstream devices to be + Zero-Touch-Provisioned over the uplink interfaces. + For L2 devices this setting also requires that + the `inband_mgmt_vlan` is set for the node. + + PREVIEW: Support for L3 devices is marked as "preview", + meaning the data models or generated configuration can change at any time. + inband_ztp_lacp_fallback_delay: + Set the LACP fallback timeout of the upstream device's port-channel towards the downstream inband + ZTP node. + This setting also requires that `inband_ztp` is set for the node. + mpls_overlay_role: + Set the default mpls overlay role. + Acting role in overlay control plane. + overlay_address_families: + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + mpls_route_reflectors: + List of inventory hostname acting as MPLS route-reflectors. + + Subclass of AvdList with `str` items. + bgp_cluster_id: Set BGP cluster id. + ptp: Subclass of AvdModel. + wan_role: + Override the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + cv_pathfinder_transit_mode: + Configure the transit mode for a WAN client for CV Pathfinder designs + only when the `wan_mode` root + key is set to `cv_pathfinder`. + + 'zone' is currently not supported. + cv_pathfinder_region: + The CV Pathfinder region name. + This key is required for WAN routers but optional for pathfinders. + The region name must be defined under 'cv_pathfinder_regions'. + cv_pathfinder_site: + The CV Pathfinder site name. + This key is required for WAN routers but optional for pathfinders. + For + WAN routers and pathfinders with `cv_pathfinder_region`, the site name must be defined for the + relevant region under 'cv_pathfinder_regions'. + For pathfinders without `cv_pathfinder_region` set, + the site must be defined under `cv_pathfinder_global_sites`. + wan_ha: + PREVIEW: This key is currently not supported + + The key is supported only if `wan_mode` == `cv- + pathfinder`. + AutoVPN support is still to be determined. + + Maximum 2 devices supported by group for + HA. + + Subclass of AvdModel. + dps_mss_ipv4: IPv4 MSS value configured under "router path-selection" on WAN Devices. + l3_interfaces: + L3 Interfaces to configure on the node. + Used to define the node for WAN interfaces when + `wan_carrier` is set. + + Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is + `name` (`str`). + data_plane_cpu_allocation_max: + Set the maximum number of CPU used for the data plane. + This setting is useful on virtual Route + Reflectors and Pathfinders where more CPU cores should be allocated for control plane. + flow_tracker_type: + Set the flow tracker type. + Override the `default_flow_tracker_type`` set at the `node_type_key` + level. + `default_flow_tracker_type` default value is `sampled`. + _custom_data: _custom_data + + """ + + class Nodes(AvdIndexedList[str, NodesItem]): + """Subclass of AvdIndexedList with `NodesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Nodes._item_type = NodesItem + + _fields: ClassVar[dict] = { + "defaults": {"type": Defaults}, + "node_groups": {"type": NodeGroups}, + "nodes": {"type": Nodes}, + "_custom_data": {"type": dict}, + } + defaults: Defaults + """ + Define variables for all nodes of this type. + + Subclass of AvdModel. + """ + node_groups: NodeGroups + """ + Define variables related to all nodes part of this group. + + Subclass of AvdIndexedList with + `NodeGroupsItem` items. Primary key is `group` (`str`). + """ + nodes: Nodes + """ + Define variables per node. + + Subclass of AvdIndexedList with `NodesItem` items. Primary key is `name` + (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + defaults: Defaults | UndefinedType = Undefined, + node_groups: NodeGroups | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + CustomNodeTypes. + + + Subclass of AvdModel. + + Args: + defaults: + Define variables for all nodes of this type. + + Subclass of AvdModel. + node_groups: + Define variables related to all nodes part of this group. + + Subclass of AvdIndexedList with + `NodeGroupsItem` items. Primary key is `group` (`str`). + nodes: + Define variables per node. + + Subclass of AvdIndexedList with `NodesItem` items. Primary key is `name` + (`str`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"key": {"type": str}, "value": {"type": CustomNodeTypes}} + _field_to_key_map: ClassVar[dict] = {"value": "custom_node_type_keys_key"} + _key_to_field_map: ClassVar[dict] = {"custom_node_type_keys_key": "value"} + key: str + """Key used as dynamic key""" + value: CustomNodeTypes + """Value of dynamic key""" + + if TYPE_CHECKING: + + def __init__(self, *, key: str | UndefinedType = Undefined, value: CustomNodeTypes | UndefinedType = Undefined) -> None: + """ + DynamicCustomNodeTypesItem. + + + Args: + key: Key used as dynamic key + value: Value of dynamic key + + """ + + class DynamicCustomNodeTypes(AvdIndexedList[str, DynamicCustomNodeTypesItem]): + _primary_key: ClassVar[str] = "key" + + DynamicCustomNodeTypes._item_type = DynamicCustomNodeTypesItem + + class DynamicNetworkServicesItem(AvdModel): + class NetworkServicesItem(AvdModel): + """Subclass of AvdModel.""" + + class BgpPeerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class Nodes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Nodes._item_type = str + + class AddressFamilyIpv4(AvdModel): + """Subclass of AvdModel.""" + + class DefaultOriginate(EosCliConfigGen.RouterBgp.AddressFamilyIpv4.PeerGroupsItem.DefaultOriginate): + """Subclass of AvdModel.""" + + class NextHop(EosCliConfigGen.RouterBgp.AddressFamilyIpv4.PeerGroupsItem.NextHop): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "default_originate": {"type": DefaultOriginate}, + "next_hop": {"type": NextHop}, + "prefix_list_in": {"type": str}, + "prefix_list_out": {"type": str}, + "_custom_data": {"type": dict}, + } + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + default_originate: DefaultOriginate + """Subclass of AvdModel.""" + next_hop: NextHop + """Subclass of AvdModel.""" + prefix_list_in: str | None + """Inbound prefix-list name.""" + prefix_list_out: str | None + """Outbound prefix-list name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + default_originate: DefaultOriginate | UndefinedType = Undefined, + next_hop: NextHop | UndefinedType = Undefined, + prefix_list_in: str | None | UndefinedType = Undefined, + prefix_list_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv4. + + + Subclass of AvdModel. + + Args: + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + default_originate: Subclass of AvdModel. + next_hop: Subclass of AvdModel. + prefix_list_in: Inbound prefix-list name. + prefix_list_out: Outbound prefix-list name. + _custom_data: _custom_data + + """ + + class AddressFamilyIpv6(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "prefix_list_in": {"type": str}, + "prefix_list_out": {"type": str}, + "_custom_data": {"type": dict}, + } + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + prefix_list_in: str | None + """Inbound prefix-list name.""" + prefix_list_out: str | None + """Outbound prefix-list name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + prefix_list_in: str | None | UndefinedType = Undefined, + prefix_list_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv6. + + + Subclass of AvdModel. + + Args: + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + prefix_list_in: Inbound prefix-list name. + prefix_list_out: Outbound prefix-list name. + _custom_data: _custom_data + + """ + + class AsPath(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "remote_as_replace_out": {"type": bool}, + "prepend_own_disabled": {"type": bool}, + "_custom_data": {"type": dict}, + } + remote_as_replace_out: bool | None + """Replace AS number with local AS number.""" + prepend_own_disabled: bool | None + """Disable prepending own AS number to AS path.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + remote_as_replace_out: bool | None | UndefinedType = Undefined, + prepend_own_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AsPath. + + + Subclass of AvdModel. + + Args: + remote_as_replace_out: Replace AS number with local AS number. + prepend_own_disabled: Disable prepending own AS number to AS path. + _custom_data: _custom_data + + """ + + class RemovePrivateAs(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "all": {"type": bool}, + "replace_as": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + all: bool | None + replace_as: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + all: bool | None | UndefinedType = Undefined, + replace_as: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemovePrivateAs. + + + Subclass of AvdModel. + + Args: + enabled: enabled + all: all + replace_as: replace_as + _custom_data: _custom_data + + """ + + class RemovePrivateAsIngress(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "replace_as": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + replace_as: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + replace_as: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemovePrivateAsIngress. + + + Subclass of AvdModel. + + Args: + enabled: enabled + replace_as: replace_as + _custom_data: _custom_data + + """ + + class BfdTimers(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "interval": {"type": int}, + "min_rx": {"type": int}, + "multiplier": {"type": int}, + "_custom_data": {"type": dict}, + } + interval: int + """Interval in milliseconds.""" + min_rx: int + """Rate in milliseconds.""" + multiplier: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | UndefinedType = Undefined, + min_rx: int | UndefinedType = Undefined, + multiplier: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BfdTimers. + + + Subclass of AvdModel. + + Args: + interval: Interval in milliseconds. + min_rx: Rate in milliseconds. + multiplier: multiplier + _custom_data: _custom_data + + """ + + class DefaultOriginate(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "always": {"type": bool}, + "route_map": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + always: bool | None + route_map: str | None + """Route-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + always: bool | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultOriginate. + + + Subclass of AvdModel. + + Args: + enabled: enabled + always: always + route_map: Route-map name. + _custom_data: _custom_data + + """ + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + class DirectionIn(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "action": {"type": str}, + "include_community_list": {"type": bool}, + "include_prefix_list": {"type": bool}, + "include_sub_route_map": {"type": bool}, + "_custom_data": {"type": dict}, + } + action: Literal["deny", "permit", "deny-in-out"] + """Missing policy action.""" + include_community_list: bool | None + """Include community-list references in missing policy decision.""" + include_prefix_list: bool | None + """Include prefix-list references in missing policy decision.""" + include_sub_route_map: bool | None + """Include sub-route-map references in missing policy decision.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["deny", "permit", "deny-in-out"] | UndefinedType = Undefined, + include_community_list: bool | None | UndefinedType = Undefined, + include_prefix_list: bool | None | UndefinedType = Undefined, + include_sub_route_map: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionIn. + + + Subclass of AvdModel. + + Args: + action: Missing policy action. + include_community_list: Include community-list references in missing policy decision. + include_prefix_list: Include prefix-list references in missing policy decision. + include_sub_route_map: Include sub-route-map references in missing policy decision. + _custom_data: _custom_data + + """ + + class DirectionOut(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "action": {"type": str}, + "include_community_list": {"type": bool}, + "include_prefix_list": {"type": bool}, + "include_sub_route_map": {"type": bool}, + "_custom_data": {"type": dict}, + } + action: Literal["deny", "permit", "deny-in-out"] + """Missing policy action.""" + include_community_list: bool | None + """Include community-list references in missing policy decision.""" + include_prefix_list: bool | None + """Include prefix-list references in missing policy decision.""" + include_sub_route_map: bool | None + """Include sub-route-map references in missing policy decision.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["deny", "permit", "deny-in-out"] | UndefinedType = Undefined, + include_community_list: bool | None | UndefinedType = Undefined, + include_prefix_list: bool | None | UndefinedType = Undefined, + include_sub_route_map: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionOut. + + + Subclass of AvdModel. + + Args: + action: Missing policy action. + include_community_list: Include community-list references in missing policy decision. + include_prefix_list: Include prefix-list references in missing policy decision. + include_sub_route_map: Include sub-route-map references in missing policy decision. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "direction_in": {"type": DirectionIn}, + "direction_out": {"type": DirectionOut}, + "_custom_data": {"type": dict}, + } + direction_in: DirectionIn + """ + Missing policy inbound direction. + + Subclass of AvdModel. + """ + direction_out: DirectionOut + """ + Missing policy outbound direction. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in: DirectionIn | UndefinedType = Undefined, + direction_out: DirectionOut | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in: + Missing policy inbound direction. + + Subclass of AvdModel. + direction_out: + Missing policy outbound direction. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class LinkBandwidth(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "default": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + default: str | None + """nn.nn(K|M|G) link speed in bits/second.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + default: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkBandwidth. + + + Subclass of AvdModel. + + Args: + enabled: enabled + default: nn.nn(K|M|G) link speed in bits/second. + _custom_data: _custom_data + + """ + + class AllowasIn(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "times": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool | None + times: int | None + """Number of local ASNs allowed in a BGP update.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + times: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AllowasIn. + + + Subclass of AvdModel. + + Args: + enabled: enabled + times: Number of local ASNs allowed in a BGP update. + _custom_data: _custom_data + + """ + + class RibInPrePolicyRetain(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "all": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + all: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + all: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RibInPrePolicyRetain. + + + Subclass of AvdModel. + + Args: + enabled: enabled + all: all + _custom_data: _custom_data + + """ + + class SharedSecret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "hash_algorithm": {"type": str}, "_custom_data": {"type": dict}} + profile: str + """Name of profile defined under `management_security`.""" + hash_algorithm: Literal["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"] + """Note: Algorithm hmac-sha-256 requires EOS version 4.31.1F and above.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + hash_algorithm: Literal["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SharedSecret. + + + Subclass of AvdModel. + + Args: + profile: Name of profile defined under `management_security`. + hash_algorithm: Note: Algorithm hmac-sha-256 requires EOS version 4.31.1F and above. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "nodes": {"type": Nodes}, + "address_family_ipv4": {"type": AddressFamilyIpv4}, + "address_family_ipv6": {"type": AddressFamilyIpv6}, + "type": {"type": str}, + "remote_as": {"type": str}, + "local_as": {"type": str}, + "description": {"type": str}, + "shutdown": {"type": bool}, + "as_path": {"type": AsPath}, + "remove_private_as": {"type": RemovePrivateAs}, + "remove_private_as_ingress": {"type": RemovePrivateAsIngress}, + "next_hop_unchanged": {"type": bool}, + "update_source": {"type": str}, + "route_reflector_client": {"type": bool}, + "bfd": {"type": bool}, + "bfd_timers": {"type": BfdTimers}, + "ebgp_multihop": {"type": int}, + "next_hop_self": {"type": bool}, + "password": {"type": str}, + "passive": {"type": bool}, + "default_originate": {"type": DefaultOriginate}, + "send_community": {"type": str}, + "maximum_routes": {"type": int}, + "maximum_routes_warning_limit": {"type": str}, + "maximum_routes_warning_only": {"type": bool}, + "missing_policy": {"type": MissingPolicy}, + "link_bandwidth": {"type": LinkBandwidth}, + "allowas_in": {"type": AllowasIn}, + "weight": {"type": int}, + "timers": {"type": str}, + "rib_in_pre_policy_retain": {"type": RibInPrePolicyRetain}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "session_tracker": {"type": str}, + "shared_secret": {"type": SharedSecret}, + "ttl_maximum_hops": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str + """BGP peer group name.""" + nodes: Nodes + """ + Nodes is required to restrict configuration of BGP neighbors to certain nodes in the network. + If not + set the peer-group is created on devices which have a bgp_peer mapped to the corresponding + peer_group. + + + Subclass of AvdList with `str` items. + """ + address_family_ipv4: AddressFamilyIpv4 + """Subclass of AvdModel.""" + address_family_ipv6: AddressFamilyIpv6 + """Subclass of AvdModel.""" + type: str | None + """Key only used for documentation or validation purposes.""" + remote_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + local_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + description: str | None + shutdown: bool | None + as_path: AsPath + """ + BGP AS-PATH options. + + Subclass of AvdModel. + """ + remove_private_as: RemovePrivateAs + """ + Remove private AS numbers in outbound AS path. + + Subclass of AvdModel. + """ + remove_private_as_ingress: RemovePrivateAsIngress + """Subclass of AvdModel.""" + next_hop_unchanged: bool | None + update_source: str | None + """IP address or interface name.""" + route_reflector_client: bool | None + bfd: bool | None + """Enable BFD.""" + bfd_timers: BfdTimers + """ + Override default BFD timers. BFD must be enabled with `bfd: true`. + + Subclass of AvdModel. + """ + ebgp_multihop: int | None + """Time-to-live in range of hops.""" + next_hop_self: bool | None + password: str | None + passive: bool | None + default_originate: DefaultOriginate + """Subclass of AvdModel.""" + send_community: str | None + """'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'.""" + maximum_routes: int | None + """Maximum number of routes (0 means unlimited).""" + maximum_routes_warning_limit: str | None + """ + Maximum number of routes after which a warning is issued (0 means never warn) or + Percentage of + maximum number of routes at which to warn ("<1-100> percent"). + """ + maximum_routes_warning_only: bool | None + missing_policy: MissingPolicy + """ + Missing policy configuration for all address-families. + + Subclass of AvdModel. + """ + link_bandwidth: LinkBandwidth + """Subclass of AvdModel.""" + allowas_in: AllowasIn + """Subclass of AvdModel.""" + weight: int | None + timers: str | None + """BGP Keepalive and Hold Timer values in seconds as string "<0-3600> <0-3600>".""" + rib_in_pre_policy_retain: RibInPrePolicyRetain + """Subclass of AvdModel.""" + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + session_tracker: str | None + shared_secret: SharedSecret + """Subclass of AvdModel.""" + ttl_maximum_hops: int | None + """Maximum number of hops.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + address_family_ipv4: AddressFamilyIpv4 | UndefinedType = Undefined, + address_family_ipv6: AddressFamilyIpv6 | UndefinedType = Undefined, + type: str | None | UndefinedType = Undefined, + remote_as: str | None | UndefinedType = Undefined, + local_as: str | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + as_path: AsPath | UndefinedType = Undefined, + remove_private_as: RemovePrivateAs | UndefinedType = Undefined, + remove_private_as_ingress: RemovePrivateAsIngress | UndefinedType = Undefined, + next_hop_unchanged: bool | None | UndefinedType = Undefined, + update_source: str | None | UndefinedType = Undefined, + route_reflector_client: bool | None | UndefinedType = Undefined, + bfd: bool | None | UndefinedType = Undefined, + bfd_timers: BfdTimers | UndefinedType = Undefined, + ebgp_multihop: int | None | UndefinedType = Undefined, + next_hop_self: bool | None | UndefinedType = Undefined, + password: str | None | UndefinedType = Undefined, + passive: bool | None | UndefinedType = Undefined, + default_originate: DefaultOriginate | UndefinedType = Undefined, + send_community: str | None | UndefinedType = Undefined, + maximum_routes: int | None | UndefinedType = Undefined, + maximum_routes_warning_limit: str | None | UndefinedType = Undefined, + maximum_routes_warning_only: bool | None | UndefinedType = Undefined, + missing_policy: MissingPolicy | UndefinedType = Undefined, + link_bandwidth: LinkBandwidth | UndefinedType = Undefined, + allowas_in: AllowasIn | UndefinedType = Undefined, + weight: int | None | UndefinedType = Undefined, + timers: str | None | UndefinedType = Undefined, + rib_in_pre_policy_retain: RibInPrePolicyRetain | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + session_tracker: str | None | UndefinedType = Undefined, + shared_secret: SharedSecret | UndefinedType = Undefined, + ttl_maximum_hops: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BgpPeerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: BGP peer group name. + nodes: + Nodes is required to restrict configuration of BGP neighbors to certain nodes in the network. + If not + set the peer-group is created on devices which have a bgp_peer mapped to the corresponding + peer_group. + + + Subclass of AvdList with `str` items. + address_family_ipv4: Subclass of AvdModel. + address_family_ipv6: Subclass of AvdModel. + type: Key only used for documentation or validation purposes. + remote_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + local_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + description: description + shutdown: shutdown + as_path: + BGP AS-PATH options. + + Subclass of AvdModel. + remove_private_as: + Remove private AS numbers in outbound AS path. + + Subclass of AvdModel. + remove_private_as_ingress: Subclass of AvdModel. + next_hop_unchanged: next_hop_unchanged + update_source: IP address or interface name. + route_reflector_client: route_reflector_client + bfd: Enable BFD. + bfd_timers: + Override default BFD timers. BFD must be enabled with `bfd: true`. + + Subclass of AvdModel. + ebgp_multihop: Time-to-live in range of hops. + next_hop_self: next_hop_self + password: password + passive: passive + default_originate: Subclass of AvdModel. + send_community: 'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'. + maximum_routes: Maximum number of routes (0 means unlimited). + maximum_routes_warning_limit: + Maximum number of routes after which a warning is issued (0 means never warn) or + Percentage of + maximum number of routes at which to warn ("<1-100> percent"). + maximum_routes_warning_only: maximum_routes_warning_only + missing_policy: + Missing policy configuration for all address-families. + + Subclass of AvdModel. + link_bandwidth: Subclass of AvdModel. + allowas_in: Subclass of AvdModel. + weight: weight + timers: BGP Keepalive and Hold Timer values in seconds as string "<0-3600> <0-3600>". + rib_in_pre_policy_retain: Subclass of AvdModel. + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + session_tracker: session_tracker + shared_secret: Subclass of AvdModel. + ttl_maximum_hops: Maximum number of hops. + _custom_data: _custom_data + + """ + + class BgpPeerGroups(AvdIndexedList[str, BgpPeerGroupsItem]): + """Subclass of AvdIndexedList with `BgpPeerGroupsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + BgpPeerGroups._item_type = BgpPeerGroupsItem + + class EvpnL2Multicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "underlay_l2_multicast_group_ipv4_pool": {"type": str}, + "underlay_l2_multicast_group_ipv4_pool_offset": {"type": int, "default": 0}, + "fast_leave": {"type": bool}, + "always_redistribute_igmp": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + underlay_l2_multicast_group_ipv4_pool: str | None + """IPv4_address/Mask.""" + underlay_l2_multicast_group_ipv4_pool_offset: int + """Default value: `0`""" + fast_leave: bool | None + """Enable IGMP snooping fast-leave feature for all SVIs and l2vlans within the Tenant.""" + always_redistribute_igmp: bool | None + """ + Always configure `redistribute igmp` under BGP for all SVIs within the Tenant if `evpn_l2_multicast` + is True. + By default `redistribute igmp` is only configured when `evpn_l2_multicast` is True and + `evpn_l3_multicast` for the VRF is False. + Configuring `redistribute igmp` when both L2 and L3 EVPN + Multicast is enabled will take up additional control-plane and data-plane resources, + but it is + required to support forwarding of TTL=1 multicast traffic within the VLAN. + This can be overridden + per SVI. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + underlay_l2_multicast_group_ipv4_pool: str | None | UndefinedType = Undefined, + underlay_l2_multicast_group_ipv4_pool_offset: int | UndefinedType = Undefined, + fast_leave: bool | None | UndefinedType = Undefined, + always_redistribute_igmp: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnL2Multicast. + + + Subclass of AvdModel. + + Args: + enabled: enabled + underlay_l2_multicast_group_ipv4_pool: IPv4_address/Mask. + underlay_l2_multicast_group_ipv4_pool_offset: underlay_l2_multicast_group_ipv4_pool_offset + fast_leave: Enable IGMP snooping fast-leave feature for all SVIs and l2vlans within the Tenant. + always_redistribute_igmp: + Always configure `redistribute igmp` under BGP for all SVIs within the Tenant if `evpn_l2_multicast` + is True. + By default `redistribute igmp` is only configured when `evpn_l2_multicast` is True and + `evpn_l3_multicast` for the VRF is False. + Configuring `redistribute igmp` when both L2 and L3 EVPN + Multicast is enabled will take up additional control-plane and data-plane resources, + but it is + required to support forwarding of TTL=1 multicast traffic within the VLAN. + This can be overridden + per SVI. + _custom_data: _custom_data + + """ + + class EvpnL3Multicast(AvdModel): + """Subclass of AvdModel.""" + + class EvpnPegItem(AvdModel): + """Subclass of AvdModel.""" + + class Nodes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Nodes._item_type = str + + _fields: ClassVar[dict] = {"nodes": {"type": Nodes}, "transit": {"type": bool}, "_custom_data": {"type": dict}} + nodes: Nodes + """ + A description will be applied to all nodes with RP addresses configured if not set. + + Subclass of + AvdList with `str` items. + """ + transit: bool | None + """Enable EVPN PEG transit mode.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + nodes: Nodes | UndefinedType = Undefined, + transit: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnPegItem. + + + Subclass of AvdModel. + + Args: + nodes: + A description will be applied to all nodes with RP addresses configured if not set. + + Subclass of + AvdList with `str` items. + transit: Enable EVPN PEG transit mode. + _custom_data: _custom_data + + """ + + class EvpnPeg(AvdList[EvpnPegItem]): + """Subclass of AvdList with `EvpnPegItem` items.""" + + EvpnPeg._item_type = EvpnPegItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "evpn_underlay_l3_multicast_group_ipv4_pool": {"type": str}, + "evpn_underlay_l3_multicast_group_ipv4_pool_offset": {"type": int, "default": 0}, + "evpn_peg": {"type": EvpnPeg}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + evpn_underlay_l3_multicast_group_ipv4_pool: str + """IPv4_address/Mask.""" + evpn_underlay_l3_multicast_group_ipv4_pool_offset: int + """Default value: `0`""" + evpn_peg: EvpnPeg + """ + For each group of nodes, allow configuration of EVPN PEG options. + The first group of settings where + the device's hostname is present in the 'nodes' list will be used. + + + Subclass of AvdList with + `EvpnPegItem` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + evpn_underlay_l3_multicast_group_ipv4_pool: str | UndefinedType = Undefined, + evpn_underlay_l3_multicast_group_ipv4_pool_offset: int | UndefinedType = Undefined, + evpn_peg: EvpnPeg | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnL3Multicast. + + + Subclass of AvdModel. + + Args: + enabled: enabled + evpn_underlay_l3_multicast_group_ipv4_pool: IPv4_address/Mask. + evpn_underlay_l3_multicast_group_ipv4_pool_offset: evpn_underlay_l3_multicast_group_ipv4_pool_offset + evpn_peg: + For each group of nodes, allow configuration of EVPN PEG options. + The first group of settings where + the device's hostname is present in the 'nodes' list will be used. + + + Subclass of AvdList with + `EvpnPegItem` items. + _custom_data: _custom_data + + """ + + class PimRpAddressesItem(AvdModel): + """Subclass of AvdModel.""" + + class Rps(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Rps._item_type = str + + class Nodes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Nodes._item_type = str + + class Groups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Groups._item_type = str + + _fields: ClassVar[dict] = { + "rps": {"type": Rps}, + "nodes": {"type": Nodes}, + "groups": {"type": Groups}, + "access_list_name": {"type": str}, + "_custom_data": {"type": dict}, + } + rps: Rps + """ + List of Rendevouz Points. + + Subclass of AvdList with `str` items. + """ + nodes: Nodes + """ + Restrict configuration to specific nodes. + Configuration Will be applied to all nodes if not set. + Subclass of AvdList with `str` items. + """ + groups: Groups + """Subclass of AvdList with `str` items.""" + access_list_name: str | None + """ + List of groups to associate with the RP address set in 'rp'. + If access_list_name is set, a standard + access-list will be configured matching these groups. + Otherwise the groups are configured directly + on the RP command. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + rps: Rps | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + access_list_name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PimRpAddressesItem. + + + Subclass of AvdModel. + + Args: + rps: + List of Rendevouz Points. + + Subclass of AvdList with `str` items. + nodes: + Restrict configuration to specific nodes. + Configuration Will be applied to all nodes if not set. + Subclass of AvdList with `str` items. + groups: Subclass of AvdList with `str` items. + access_list_name: + List of groups to associate with the RP address set in 'rp'. + If access_list_name is set, a standard + access-list will be configured matching these groups. + Otherwise the groups are configured directly + on the RP command. + _custom_data: _custom_data + + """ + + class PimRpAddresses(AvdList[PimRpAddressesItem]): + """Subclass of AvdList with `PimRpAddressesItem` items.""" + + PimRpAddresses._item_type = PimRpAddressesItem + + class IgmpSnoopingQuerier(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "source_address": {"type": str}, + "version": {"type": int}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Will be enabled automatically if "evpn_l2_multicast" is enabled.""" + source_address: str | None + """Default IP address of Loopback0.""" + version: Literal[1, 2, 3] | None + """IGMP Version (By default EOS uses IGMP version 2 for IGMP querier).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + source_address: str | None | UndefinedType = Undefined, + version: Literal[1, 2, 3] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IgmpSnoopingQuerier. + + + Subclass of AvdModel. + + Args: + enabled: Will be enabled automatically if "evpn_l2_multicast" is enabled. + source_address: Default IP address of Loopback0. + version: IGMP Version (By default EOS uses IGMP version 2 for IGMP querier). + _custom_data: _custom_data + + """ + + class VrfsItem(AvdModel): + """Subclass of AvdModel.""" + + class AddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AddressFamilies._item_type = str + + class IpHelpersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "ip_helper": {"type": str}, + "source_interface": {"type": str}, + "source_vrf": {"type": str}, + "_custom_data": {"type": dict}, + } + ip_helper: str + """IPv4 DHCP server IP.""" + source_interface: str | None + """Interface name.""" + source_vrf: str | None + """VRF to originate DHCP relay packets to DHCP server. If not set, uses current VRF.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_helper: str | UndefinedType = Undefined, + source_interface: str | None | UndefinedType = Undefined, + source_vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpHelpersItem. + + + Subclass of AvdModel. + + Args: + ip_helper: IPv4 DHCP server IP. + source_interface: Interface name. + source_vrf: VRF to originate DHCP relay packets to DHCP server. If not set, uses current VRF. + _custom_data: _custom_data + + """ + + class IpHelpers(AvdIndexedList[str, IpHelpersItem]): + """Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is `ip_helper` (`str`).""" + + _primary_key: ClassVar[str] = "ip_helper" + + IpHelpers._item_type = IpHelpersItem + + class VtepDiagnostic(AvdModel): + """Subclass of AvdModel.""" + + class LoopbackIpPoolsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "pod": {"type": str}, + "ipv4_pool": {"type": str}, + "ipv6_pool": {"type": str}, + "_custom_data": {"type": dict}, + } + pod: str + """POD name.""" + ipv4_pool: str | None + """IPv4_address/Mask.""" + ipv6_pool: str | None + """IPv6_address/Mask.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + pod: str | UndefinedType = Undefined, + ipv4_pool: str | None | UndefinedType = Undefined, + ipv6_pool: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LoopbackIpPoolsItem. + + + Subclass of AvdModel. + + Args: + pod: POD name. + ipv4_pool: IPv4_address/Mask. + ipv6_pool: IPv6_address/Mask. + _custom_data: _custom_data + + """ + + class LoopbackIpPools(AvdIndexedList[str, LoopbackIpPoolsItem]): + """Subclass of AvdIndexedList with `LoopbackIpPoolsItem` items. Primary key is `pod` (`str`).""" + + _primary_key: ClassVar[str] = "pod" + + LoopbackIpPools._item_type = LoopbackIpPoolsItem + + _fields: ClassVar[dict] = { + "loopback": {"type": int}, + "loopback_description": {"type": str}, + "loopback_ip_range": {"type": str}, + "loopback_ipv6_range": {"type": str}, + "loopback_ip_pools": {"type": LoopbackIpPools}, + "_custom_data": {"type": dict}, + } + loopback: int | None + """Loopback interface number, required when vtep_diagnotics defined.""" + loopback_description: str | None + """ + Provide a custom description or description template to be used on the VRF diagnostic loopback + interface. + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `interface`: The Loopback interface + name. + - `vrf`: The VRF name. + - `tenant`: The tenant name. + + The default description is set by + `default_vrf_diag_loopback_description`. + By default the description is templated from the VRF name. + """ + loopback_ip_range: str | None + """ + IPv4_address/Mask. + Loopback IPv4 range, a unique ip is derived from this range and assigned to each + l3 leaf based on it's unique id. + Loopback is not created unless `loopback_ip_range`, + `loopback_ipv6_range` or `loopback_ip_pools` are set. + """ + loopback_ipv6_range: str | None + """ + IPv6_address/Mask. + Loopback IPv6 range, a unique IPv6 address is derived from this range and + assigned to each L3 leaf based on it's unique ID. + Loopback is not created unless + `loopback_ip_range`, `loopback_ipv6_range` or `loopback_ip_pools` are set. + """ + loopback_ip_pools: LoopbackIpPools + """ + For inventories with multiple PODs a loopback range can be set per POD to avoid overlaps. + `loopback_ip_range` takes precedence for IPv4 and `loopback_ipv6_range` takes precedence for IPV6. + Loopback is not created unless `loopback_ip_range`, `loopback_ipv6_range` or `loopback_ip_pools` are + set. + + + Subclass of AvdIndexedList with `LoopbackIpPoolsItem` items. Primary key is `pod` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + loopback: int | None | UndefinedType = Undefined, + loopback_description: str | None | UndefinedType = Undefined, + loopback_ip_range: str | None | UndefinedType = Undefined, + loopback_ipv6_range: str | None | UndefinedType = Undefined, + loopback_ip_pools: LoopbackIpPools | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VtepDiagnostic. + + + Subclass of AvdModel. + + Args: + loopback: Loopback interface number, required when vtep_diagnotics defined. + loopback_description: + Provide a custom description or description template to be used on the VRF diagnostic loopback + interface. + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `interface`: The Loopback interface + name. + - `vrf`: The VRF name. + - `tenant`: The tenant name. + + The default description is set by + `default_vrf_diag_loopback_description`. + By default the description is templated from the VRF name. + loopback_ip_range: + IPv4_address/Mask. + Loopback IPv4 range, a unique ip is derived from this range and assigned to each + l3 leaf based on it's unique id. + Loopback is not created unless `loopback_ip_range`, + `loopback_ipv6_range` or `loopback_ip_pools` are set. + loopback_ipv6_range: + IPv6_address/Mask. + Loopback IPv6 range, a unique IPv6 address is derived from this range and + assigned to each L3 leaf based on it's unique ID. + Loopback is not created unless + `loopback_ip_range`, `loopback_ipv6_range` or `loopback_ip_pools` are set. + loopback_ip_pools: + For inventories with multiple PODs a loopback range can be set per POD to avoid overlaps. + `loopback_ip_range` takes precedence for IPv4 and `loopback_ipv6_range` takes precedence for IPV6. + Loopback is not created unless `loopback_ip_range`, `loopback_ipv6_range` or `loopback_ip_pools` are + set. + + + Subclass of AvdIndexedList with `LoopbackIpPoolsItem` items. Primary key is `pod` (`str`). + _custom_data: _custom_data + + """ + + class Ospf(AvdModel): + """Subclass of AvdModel.""" + + class RedistributeBgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool, "default": True}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + """Default value: `True`""" + route_map: str | None + """Route-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RedistributeBgp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: Route-map name. + _custom_data: _custom_data + + """ + + class RedistributeConnected(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool, "default": False}, "route_map": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool + """Default value: `False`""" + route_map: str | None + """Route-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RedistributeConnected. + + + Subclass of AvdModel. + + Args: + enabled: enabled + route_map: Route-map name. + _custom_data: _custom_data + + """ + + class Nodes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Nodes._item_type = str + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "process_id": {"type": int}, + "router_id": {"type": str}, + "max_lsa": {"type": int}, + "bfd": {"type": bool, "default": False}, + "redistribute_bgp": {"type": RedistributeBgp}, + "redistribute_connected": {"type": RedistributeConnected}, + "nodes": {"type": Nodes}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + process_id: int | None + """If not set, "vrf_id" will be used.""" + router_id: str | None + """If not set, switch router_id will be used.""" + max_lsa: int | None + bfd: bool + """Default value: `False`""" + redistribute_bgp: RedistributeBgp + """Subclass of AvdModel.""" + redistribute_connected: RedistributeConnected + """Subclass of AvdModel.""" + nodes: Nodes + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + process_id: int | None | UndefinedType = Undefined, + router_id: str | None | UndefinedType = Undefined, + max_lsa: int | None | UndefinedType = Undefined, + bfd: bool | UndefinedType = Undefined, + redistribute_bgp: RedistributeBgp | UndefinedType = Undefined, + redistribute_connected: RedistributeConnected | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospf. + + + Subclass of AvdModel. + + Args: + enabled: enabled + process_id: If not set, "vrf_id" will be used. + router_id: If not set, switch router_id will be used. + max_lsa: max_lsa + bfd: bfd + redistribute_bgp: Subclass of AvdModel. + redistribute_connected: Subclass of AvdModel. + nodes: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class EvpnL3Multicast(AvdModel): + """Subclass of AvdModel.""" + + class EvpnPegItem(AvdModel): + """Subclass of AvdModel.""" + + class Nodes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Nodes._item_type = str + + _fields: ClassVar[dict] = {"nodes": {"type": Nodes}, "transit": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + nodes: Nodes + """ + Restrict configuration to specific nodes. + Will apply to all nodes with RP addresses configured if + not set. + + + Subclass of AvdList with `str` items. + """ + transit: bool + """ + Enable EVPN PEG transit mode. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + nodes: Nodes | UndefinedType = Undefined, + transit: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnPegItem. + + + Subclass of AvdModel. + + Args: + nodes: + Restrict configuration to specific nodes. + Will apply to all nodes with RP addresses configured if + not set. + + + Subclass of AvdList with `str` items. + transit: Enable EVPN PEG transit mode. + _custom_data: _custom_data + + """ + + class EvpnPeg(AvdList[EvpnPegItem]): + """Subclass of AvdList with `EvpnPegItem` items.""" + + EvpnPeg._item_type = EvpnPegItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "evpn_underlay_l3_multicast_group": {"type": str}, + "evpn_peg": {"type": EvpnPeg}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + evpn_underlay_l3_multicast_group: str | None + """ + IPv4 address of evpn underlay l3 multicast group. + To override multicast range set using the formula + < l3_multicast.evpn_underlay_l3_multicast_group_ipv4_pool > + < vrf_id - 1 > + < + l3_multicast.evpn_underlay_l3_multicast_group_ipv4_pool_offset >. + """ + evpn_peg: EvpnPeg + """ + For each group of nodes, allow configuration of EVPN PEG features. + + Subclass of AvdList with + `EvpnPegItem` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + evpn_underlay_l3_multicast_group: str | None | UndefinedType = Undefined, + evpn_peg: EvpnPeg | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnL3Multicast. + + + Subclass of AvdModel. + + Args: + enabled: enabled + evpn_underlay_l3_multicast_group: + IPv4 address of evpn underlay l3 multicast group. + To override multicast range set using the formula + < l3_multicast.evpn_underlay_l3_multicast_group_ipv4_pool > + < vrf_id - 1 > + < + l3_multicast.evpn_underlay_l3_multicast_group_ipv4_pool_offset >. + evpn_peg: + For each group of nodes, allow configuration of EVPN PEG features. + + Subclass of AvdList with + `EvpnPegItem` items. + _custom_data: _custom_data + + """ + + class PimRpAddressesItem(AvdModel): + """Subclass of AvdModel.""" + + class Rps(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Rps._item_type = str + + class Nodes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Nodes._item_type = str + + class Groups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Groups._item_type = str + + _fields: ClassVar[dict] = { + "rps": {"type": Rps}, + "nodes": {"type": Nodes}, + "groups": {"type": Groups}, + "access_list_name": {"type": str}, + "_custom_data": {"type": dict}, + } + rps: Rps + """ + A minimum of one RP must be specified. + + Subclass of AvdList with `str` items. + """ + nodes: Nodes + """ + Restrict configuration to specific nodes. + Configuration Will be applied to all nodes if not set. + Subclass of AvdList with `str` items. + """ + groups: Groups + """Subclass of AvdList with `str` items.""" + access_list_name: str | None + """ + List of groups to associate with the RP addresses set in 'rps'. + If access_list_name is set, a + standard access-list will be configured matching these groups. + Otherwise the groups are configured + directly on the RP command. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + rps: Rps | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + access_list_name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PimRpAddressesItem. + + + Subclass of AvdModel. + + Args: + rps: + A minimum of one RP must be specified. + + Subclass of AvdList with `str` items. + nodes: + Restrict configuration to specific nodes. + Configuration Will be applied to all nodes if not set. + Subclass of AvdList with `str` items. + groups: Subclass of AvdList with `str` items. + access_list_name: + List of groups to associate with the RP addresses set in 'rps'. + If access_list_name is set, a + standard access-list will be configured matching these groups. + Otherwise the groups are configured + directly on the RP command. + _custom_data: _custom_data + + """ + + class PimRpAddresses(AvdList[PimRpAddressesItem]): + """Subclass of AvdList with `PimRpAddressesItem` items.""" + + PimRpAddresses._item_type = PimRpAddressesItem + + class SvisItem(AvdModel): + """Subclass of AvdModel.""" + + class Tags(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tags._item_type = str + + class NodesItem(AvdModel): + """Subclass of AvdModel.""" + + class Tags(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tags._item_type = str + + class Ipv6AddressVirtuals(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Ipv6AddressVirtuals._item_type = str + + class IpAddressVirtualSecondaries(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + IpAddressVirtualSecondaries._item_type = str + + class IpVirtualRouterAddresses(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + IpVirtualRouterAddresses._item_type = str + + class Ipv6VirtualRouterAddresses(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Ipv6VirtualRouterAddresses._item_type = str + + class IpHelpersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "ip_helper": {"type": str}, + "source_interface": {"type": str}, + "source_vrf": {"type": str}, + "_custom_data": {"type": dict}, + } + ip_helper: str + """IPv4 DHCP server IP.""" + source_interface: str | None + """Interface name to originate DHCP relay packets to DHCP server.""" + source_vrf: str | None + """VRF to originate DHCP relay packets to DHCP server. If not set, EOS uses the VRF on the SVI.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_helper: str | UndefinedType = Undefined, + source_interface: str | None | UndefinedType = Undefined, + source_vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpHelpersItem. + + + Subclass of AvdModel. + + Args: + ip_helper: IPv4 DHCP server IP. + source_interface: Interface name to originate DHCP relay packets to DHCP server. + source_vrf: VRF to originate DHCP relay packets to DHCP server. If not set, EOS uses the VRF on the SVI. + _custom_data: _custom_data + + """ + + class IpHelpers(AvdIndexedList[str, IpHelpersItem]): + """Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is `ip_helper` (`str`).""" + + _primary_key: ClassVar[str] = "ip_helper" + + IpHelpers._item_type = IpHelpersItem + + class TrunkGroups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + TrunkGroups._item_type = str + + class EvpnL2Multicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "always_redistribute_igmp": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + always_redistribute_igmp: bool | None + """ + Always configure `redistribute igmp` under BGP for the VLAN. Overrides the setting of + `.[].evpn_l2_multicast.always_redistribute_igmp`. + By default `redistribute + igmp` is only configured when `evpn_l2_multicast` is True and `evpn_l3_multicast` for the VRF is + False. + Configuring `redistribute igmp` when both L2 and L3 EVPN Multicast is enabled will take up + additional control-plane and data-plane resources, + but it is required to support forwarding of TTL=1 + multicast traffic within the VLAN. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + always_redistribute_igmp: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnL2Multicast. + + + Subclass of AvdModel. + + Args: + enabled: enabled + always_redistribute_igmp: + Always configure `redistribute igmp` under BGP for the VLAN. Overrides the setting of + `.[].evpn_l2_multicast.always_redistribute_igmp`. + By default `redistribute + igmp` is only configured when `evpn_l2_multicast` is True and `evpn_l3_multicast` for the VRF is + False. + Configuring `redistribute igmp` when both L2 and L3 EVPN Multicast is enabled will take up + additional control-plane and data-plane resources, + but it is required to support forwarding of TTL=1 + multicast traffic within the VLAN. + _custom_data: _custom_data + + """ + + class EvpnL3Multicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, enabled: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + EvpnL3Multicast. + + + Subclass of AvdModel. + + Args: + enabled: enabled + _custom_data: _custom_data + + """ + + class IgmpSnoopingQuerier(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "source_address": {"type": str}, + "version": {"type": int}, + "fast_leave": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Will be enabled automatically if evpn_l2_multicast is enabled.""" + source_address: str | None + """ + IPv4_address + If not set, IP address of "Loopback0" will be used. + """ + version: Literal[1, 2, 3] | None + """IGMP Version (By default EOS uses IGMP version 2 for IGMP querier).""" + fast_leave: bool | None + """Enable IGMP snooping fast-leave feature.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + source_address: str | None | UndefinedType = Undefined, + version: Literal[1, 2, 3] | None | UndefinedType = Undefined, + fast_leave: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IgmpSnoopingQuerier. + + + Subclass of AvdModel. + + Args: + enabled: Will be enabled automatically if evpn_l2_multicast is enabled. + source_address: + IPv4_address + If not set, IP address of "Loopback0" will be used. + version: IGMP Version (By default EOS uses IGMP version 2 for IGMP querier). + fast_leave: Enable IGMP snooping fast-leave feature. + _custom_data: _custom_data + + """ + + class Ospf(AvdModel): + """Subclass of AvdModel.""" + + class MessageDigestKeysItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "hash_algorithm": {"type": str, "default": "sha512"}, + "key": {"type": str}, + "_custom_data": {"type": dict}, + } + id: int | None + hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] + """Default value: `"sha512"`""" + key: str | None + """Type 7 encrypted key.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | None | UndefinedType = Undefined, + hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MessageDigestKeysItem. + + + Subclass of AvdModel. + + Args: + id: id + hash_algorithm: hash_algorithm + key: Type 7 encrypted key. + _custom_data: _custom_data + + """ + + class MessageDigestKeys(AvdList[MessageDigestKeysItem]): + """Subclass of AvdList with `MessageDigestKeysItem` items.""" + + MessageDigestKeys._item_type = MessageDigestKeysItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "point_to_point": {"type": bool, "default": False}, + "area": {"type": str, "default": "0.0.0.0"}, + "cost": {"type": int}, + "authentication": {"type": str}, + "simple_auth_key": {"type": str}, + "message_digest_keys": {"type": MessageDigestKeys}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + point_to_point: bool + """Default value: `False`""" + area: str + """ + OSPF area ID. + + Default value: `"0.0.0.0"` + """ + cost: int | None + """OSPF link cost.""" + authentication: Literal["simple", "message-digest"] | None + simple_auth_key: str | None + """Password used with simple authentication.""" + message_digest_keys: MessageDigestKeys + """Subclass of AvdList with `MessageDigestKeysItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + point_to_point: bool | UndefinedType = Undefined, + area: str | UndefinedType = Undefined, + cost: int | None | UndefinedType = Undefined, + authentication: Literal["simple", "message-digest"] | None | UndefinedType = Undefined, + simple_auth_key: str | None | UndefinedType = Undefined, + message_digest_keys: MessageDigestKeys | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospf. + + + Subclass of AvdModel. + + Args: + enabled: enabled + point_to_point: point_to_point + area: OSPF area ID. + cost: OSPF link cost. + authentication: authentication + simple_auth_key: Password used with simple authentication. + message_digest_keys: Subclass of AvdList with `MessageDigestKeysItem` items. + _custom_data: _custom_data + + """ + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class StructuredConfig(EosCliConfigGen.RouterBgp.VlansItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "structured_config": {"type": StructuredConfig}, + "raw_eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + structured_config: StructuredConfig + """ + Structured configuration and EOS CLI commands rendered on router_bgp.vlans.[id=]. + This + configuration will not be applied to vlan aware bundles. + + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the Router BGP, VLAN definition in the final EOS configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + structured_config: StructuredConfig | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + structured_config: + Structured configuration and EOS CLI commands rendered on router_bgp.vlans.[id=]. + This + configuration will not be applied to vlan aware bundles. + + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the Router BGP, VLAN definition in the final EOS configuration. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "node": {"type": str}, + "tags": {"type": Tags, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "name": {"type": str}, + "enabled": {"type": bool}, + "description": {"type": str}, + "ip_address": {"type": str}, + "ipv6_address": {"type": str}, + "ipv6_enable": {"type": bool}, + "ip_address_virtual": {"type": str}, + "ipv6_address_virtuals": {"type": Ipv6AddressVirtuals}, + "ip_address_virtual_secondaries": {"type": IpAddressVirtualSecondaries}, + "ip_virtual_router_addresses": {"type": IpVirtualRouterAddresses}, + "ipv6_virtual_router_addresses": {"type": Ipv6VirtualRouterAddresses}, + "ipv4_acl_in": {"type": str}, + "ipv4_acl_out": {"type": str}, + "ip_helpers": {"type": IpHelpers}, + "vni_override": {"type": int}, + "rt_override": {"type": str}, + "rd_override": {"type": str}, + "trunk_groups": {"type": TrunkGroups}, + "evpn_l2_multicast": {"type": EvpnL2Multicast}, + "evpn_l3_multicast": {"type": EvpnL3Multicast}, + "igmp_snooping_enabled": {"type": bool}, + "igmp_snooping_querier": {"type": IgmpSnoopingQuerier}, + "vxlan": {"type": bool, "default": True}, + "spanning_tree_priority": {"type": int}, + "mtu": {"type": int}, + "ospf": {"type": Ospf}, + "bgp": {"type": Bgp}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "evpn_l2_multi_domain": {"type": bool}, + "_custom_data": {"type": dict}, + } + node: str + """Node inventory hostname.""" + tags: Tags + """ + Tags leveraged for networks services filtering. + Tags are matched against "filter.tags" defined under + node type settings. + Tags are also matched against the "node_group" name under node type settings. + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + name: str | None + """VLAN name.""" + enabled: bool | None + """Enable or disable interface.""" + description: str | None + """SVI description. By default set to VLAN name.""" + ip_address: str | None + """IPv4_address/Mask. Usually set under "nodes" to have unique IPv4 addresses per node.""" + ipv6_address: str | None + """IPv6_address/Mask. Usually set under "nodes" to have unique IPv6 addresses per node.""" + ipv6_enable: bool | None + """Explicitly enable/disable link-local IPv6 addressing.""" + ip_address_virtual: str | None + """ + IPv4_address/Mask. + IPv4 VXLAN Anycast IP address. + Conserves IP addresses in VXLAN deployments as it + doesn't require unique IP addresses on each node. + """ + ipv6_address_virtuals: Ipv6AddressVirtuals + """ + IPv6 VXLAN Anycast IP addresses. + Conserves IPv6 addresses in VXLAN deployments as it doesn't require + unique IPv6 addresses on each node. + + + Subclass of AvdList with `str` items. + """ + ip_address_virtual_secondaries: IpAddressVirtualSecondaries + """ + Secondary IPv4 VXLAN Anycast IP addresses. + + Subclass of AvdList with `str` items. + """ + ip_virtual_router_addresses: IpVirtualRouterAddresses + """ + IPv4 VARP addresses. + Requires an IP address to be configured on the SVI. + If ip_address_virtual is + also set, ip_virtual_router_addresses will take precedence + _if_ there is an ip_address configured + for the node. + + + Subclass of AvdList with `str` items. + """ + ipv6_virtual_router_addresses: Ipv6VirtualRouterAddresses + """ + IPv6 VARP addresses. + Requires an IPv6 address to be configured on the SVI. + If ipv6_address_virtuals + is also set, ipv6_virtual_router_addresses will take precedence + _if_ there is an ipv6_address + configured for the node. + + + Subclass of AvdList with `str` items. + """ + ipv4_acl_in: str | None + """ + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports substitution of the field "interface_ip". + """ + ipv4_acl_out: str | None + """ + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports substitution of the field "interface_ip". + """ + ip_helpers: IpHelpers + """ + IP helper for DHCP relay. + + Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is + `ip_helper` (`str`). + """ + vni_override: int | None + """ + By default the VNI will be derived from "mac_vrf_vni_base". + The vni_override allows us to override + this value and statically define it (optional). + """ + rt_override: str | None + """ + By default the MAC VRF RT will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rt_override will default to vni_override if set. + rt_override supports two formats: + - A single number which will be used in the RT fields instead of + mac_vrf_id/mac_vrf_vni (see 'overlay_rt_type' for details). + - A full RT string with colon + separator which will override the full RT. + """ + rd_override: str | None + """ + By default the MAC VRF RD will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rd_override will default to rt_override or + vni_override if set. + + rd_override supports two formats: + - A single number which will be used in + the RD assigned number field instead of mac_vrf_id/mac_vrf_vni (see 'overlay_rd_type' for details). + - A full RD string with colon separator which will override the full RD. + """ + trunk_groups: TrunkGroups + """Subclass of AvdList with `str` items.""" + evpn_l2_multicast: EvpnL2Multicast + """ + Explicitly enable or disable evpn_l2_multicast to override setting of + `.[].evpn_l2_multicast.enabled`. + When evpn_l2_multicast.enabled is set to true + for a vlan or a tenant, "igmp snooping" and "igmp snooping querier" will always be enabled, + overriding those individual settings. + Requires `evpn_multicast` to also be set to `true`. + + + Subclass + of AvdModel. + """ + evpn_l3_multicast: EvpnL3Multicast + """ + Explicitly enable or disable evpn_l3_multicast to override setting of + `.[].evpn_l3_multicast.enabled` and + `.[].vrfs.[].evpn_l3_multicast.enabled`. + Requires `evpn_multicast` to also be + set to `true`. + + + Subclass of AvdModel. + """ + igmp_snooping_enabled: bool | None + """Enable or disable IGMP snooping (Enabled by default on EOS).""" + igmp_snooping_querier: IgmpSnoopingQuerier + """Subclass of AvdModel.""" + vxlan: bool + """ + Extend this SVI over VXLAN. + + Default value: `True` + """ + spanning_tree_priority: int | None + """ + Setting spanning-tree priority per VLAN is only supported with `spanning_tree_mode: rapid-pvst` + under node type settings. + The default priority for rapid-PVST is set under the node type settings + with `spanning_tree_priority` (default=32768). + """ + mtu: int | None + """Interface MTU.""" + ospf: Ospf + """ + OSPF interface configuration. + + Subclass of AvdModel. + """ + bgp: Bgp + """Subclass of AvdModel.""" + raw_eos_cli: str | None + """EOS CLI rendered directly on the VLAN interface in the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config added under vlan_interfaces.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + """ + evpn_l2_multi_domain: bool | None + """ + Explicitly extend SVI to remote EVPN domains. + Overrides + `[].evpn_l2_multi_domain` and + `[].vrfs[].evpn_l2_multi_domain`. + Not supported in conjunction with EVPN vlan + aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` + or `[].vrfs[].svis[].evpn_vlan_bundle`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + node: str | UndefinedType = Undefined, + tags: Tags | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + enabled: bool | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + ipv6_address: str | None | UndefinedType = Undefined, + ipv6_enable: bool | None | UndefinedType = Undefined, + ip_address_virtual: str | None | UndefinedType = Undefined, + ipv6_address_virtuals: Ipv6AddressVirtuals | UndefinedType = Undefined, + ip_address_virtual_secondaries: IpAddressVirtualSecondaries | UndefinedType = Undefined, + ip_virtual_router_addresses: IpVirtualRouterAddresses | UndefinedType = Undefined, + ipv6_virtual_router_addresses: Ipv6VirtualRouterAddresses | UndefinedType = Undefined, + ipv4_acl_in: str | None | UndefinedType = Undefined, + ipv4_acl_out: str | None | UndefinedType = Undefined, + ip_helpers: IpHelpers | UndefinedType = Undefined, + vni_override: int | None | UndefinedType = Undefined, + rt_override: str | None | UndefinedType = Undefined, + rd_override: str | None | UndefinedType = Undefined, + trunk_groups: TrunkGroups | UndefinedType = Undefined, + evpn_l2_multicast: EvpnL2Multicast | UndefinedType = Undefined, + evpn_l3_multicast: EvpnL3Multicast | UndefinedType = Undefined, + igmp_snooping_enabled: bool | None | UndefinedType = Undefined, + igmp_snooping_querier: IgmpSnoopingQuerier | UndefinedType = Undefined, + vxlan: bool | UndefinedType = Undefined, + spanning_tree_priority: int | None | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + ospf: Ospf | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + evpn_l2_multi_domain: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NodesItem. + + + Subclass of AvdModel. + + Args: + node: Node inventory hostname. + tags: + Tags leveraged for networks services filtering. + Tags are matched against "filter.tags" defined under + node type settings. + Tags are also matched against the "node_group" name under node type settings. + Subclass of AvdList with `str` items. + name: VLAN name. + enabled: Enable or disable interface. + description: SVI description. By default set to VLAN name. + ip_address: IPv4_address/Mask. Usually set under "nodes" to have unique IPv4 addresses per node. + ipv6_address: IPv6_address/Mask. Usually set under "nodes" to have unique IPv6 addresses per node. + ipv6_enable: Explicitly enable/disable link-local IPv6 addressing. + ip_address_virtual: + IPv4_address/Mask. + IPv4 VXLAN Anycast IP address. + Conserves IP addresses in VXLAN deployments as it + doesn't require unique IP addresses on each node. + ipv6_address_virtuals: + IPv6 VXLAN Anycast IP addresses. + Conserves IPv6 addresses in VXLAN deployments as it doesn't require + unique IPv6 addresses on each node. + + + Subclass of AvdList with `str` items. + ip_address_virtual_secondaries: + Secondary IPv4 VXLAN Anycast IP addresses. + + Subclass of AvdList with `str` items. + ip_virtual_router_addresses: + IPv4 VARP addresses. + Requires an IP address to be configured on the SVI. + If ip_address_virtual is + also set, ip_virtual_router_addresses will take precedence + _if_ there is an ip_address configured + for the node. + + + Subclass of AvdList with `str` items. + ipv6_virtual_router_addresses: + IPv6 VARP addresses. + Requires an IPv6 address to be configured on the SVI. + If ipv6_address_virtuals + is also set, ipv6_virtual_router_addresses will take precedence + _if_ there is an ipv6_address + configured for the node. + + + Subclass of AvdList with `str` items. + ipv4_acl_in: + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports substitution of the field "interface_ip". + ipv4_acl_out: + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports substitution of the field "interface_ip". + ip_helpers: + IP helper for DHCP relay. + + Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is + `ip_helper` (`str`). + vni_override: + By default the VNI will be derived from "mac_vrf_vni_base". + The vni_override allows us to override + this value and statically define it (optional). + rt_override: + By default the MAC VRF RT will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rt_override will default to vni_override if set. + rt_override supports two formats: + - A single number which will be used in the RT fields instead of + mac_vrf_id/mac_vrf_vni (see 'overlay_rt_type' for details). + - A full RT string with colon + separator which will override the full RT. + rd_override: + By default the MAC VRF RD will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rd_override will default to rt_override or + vni_override if set. + + rd_override supports two formats: + - A single number which will be used in + the RD assigned number field instead of mac_vrf_id/mac_vrf_vni (see 'overlay_rd_type' for details). + - A full RD string with colon separator which will override the full RD. + trunk_groups: Subclass of AvdList with `str` items. + evpn_l2_multicast: + Explicitly enable or disable evpn_l2_multicast to override setting of + `.[].evpn_l2_multicast.enabled`. + When evpn_l2_multicast.enabled is set to true + for a vlan or a tenant, "igmp snooping" and "igmp snooping querier" will always be enabled, + overriding those individual settings. + Requires `evpn_multicast` to also be set to `true`. + + + Subclass + of AvdModel. + evpn_l3_multicast: + Explicitly enable or disable evpn_l3_multicast to override setting of + `.[].evpn_l3_multicast.enabled` and + `.[].vrfs.[].evpn_l3_multicast.enabled`. + Requires `evpn_multicast` to also be + set to `true`. + + + Subclass of AvdModel. + igmp_snooping_enabled: Enable or disable IGMP snooping (Enabled by default on EOS). + igmp_snooping_querier: Subclass of AvdModel. + vxlan: Extend this SVI over VXLAN. + spanning_tree_priority: + Setting spanning-tree priority per VLAN is only supported with `spanning_tree_mode: rapid-pvst` + under node type settings. + The default priority for rapid-PVST is set under the node type settings + with `spanning_tree_priority` (default=32768). + mtu: Interface MTU. + ospf: + OSPF interface configuration. + + Subclass of AvdModel. + bgp: Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the VLAN interface in the final EOS configuration. + structured_config: + Custom structured config added under vlan_interfaces.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + evpn_l2_multi_domain: + Explicitly extend SVI to remote EVPN domains. + Overrides + `[].evpn_l2_multi_domain` and + `[].vrfs[].evpn_l2_multi_domain`. + Not supported in conjunction with EVPN vlan + aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` + or `[].vrfs[].svis[].evpn_vlan_bundle`. + _custom_data: _custom_data + + """ + + class Nodes(AvdIndexedList[str, NodesItem]): + """Subclass of AvdIndexedList with `NodesItem` items. Primary key is `node` (`str`).""" + + _primary_key: ClassVar[str] = "node" + + Nodes._item_type = NodesItem + + class Ipv6AddressVirtuals(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Ipv6AddressVirtuals._item_type = str + + class IpAddressVirtualSecondaries(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + IpAddressVirtualSecondaries._item_type = str + + class IpVirtualRouterAddresses(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + IpVirtualRouterAddresses._item_type = str + + class Ipv6VirtualRouterAddresses(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Ipv6VirtualRouterAddresses._item_type = str + + class IpHelpersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "ip_helper": {"type": str}, + "source_interface": {"type": str}, + "source_vrf": {"type": str}, + "_custom_data": {"type": dict}, + } + ip_helper: str + """IPv4 DHCP server IP.""" + source_interface: str | None + """Interface name to originate DHCP relay packets to DHCP server.""" + source_vrf: str | None + """VRF to originate DHCP relay packets to DHCP server. If not set, EOS uses the VRF on the SVI.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_helper: str | UndefinedType = Undefined, + source_interface: str | None | UndefinedType = Undefined, + source_vrf: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpHelpersItem. + + + Subclass of AvdModel. + + Args: + ip_helper: IPv4 DHCP server IP. + source_interface: Interface name to originate DHCP relay packets to DHCP server. + source_vrf: VRF to originate DHCP relay packets to DHCP server. If not set, EOS uses the VRF on the SVI. + _custom_data: _custom_data + + """ + + class IpHelpers(AvdIndexedList[str, IpHelpersItem]): + """Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is `ip_helper` (`str`).""" + + _primary_key: ClassVar[str] = "ip_helper" + + IpHelpers._item_type = IpHelpersItem + + class TrunkGroups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + TrunkGroups._item_type = str + + class EvpnL2Multicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "always_redistribute_igmp": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + always_redistribute_igmp: bool | None + """ + Always configure `redistribute igmp` under BGP for the VLAN. Overrides the setting of + `.[].evpn_l2_multicast.always_redistribute_igmp`. + By default `redistribute + igmp` is only configured when `evpn_l2_multicast` is True and `evpn_l3_multicast` for the VRF is + False. + Configuring `redistribute igmp` when both L2 and L3 EVPN Multicast is enabled will take up + additional control-plane and data-plane resources, + but it is required to support forwarding of TTL=1 + multicast traffic within the VLAN. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + always_redistribute_igmp: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnL2Multicast. + + + Subclass of AvdModel. + + Args: + enabled: enabled + always_redistribute_igmp: + Always configure `redistribute igmp` under BGP for the VLAN. Overrides the setting of + `.[].evpn_l2_multicast.always_redistribute_igmp`. + By default `redistribute + igmp` is only configured when `evpn_l2_multicast` is True and `evpn_l3_multicast` for the VRF is + False. + Configuring `redistribute igmp` when both L2 and L3 EVPN Multicast is enabled will take up + additional control-plane and data-plane resources, + but it is required to support forwarding of TTL=1 + multicast traffic within the VLAN. + _custom_data: _custom_data + + """ + + class EvpnL3Multicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, enabled: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + EvpnL3Multicast. + + + Subclass of AvdModel. + + Args: + enabled: enabled + _custom_data: _custom_data + + """ + + class IgmpSnoopingQuerier(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "source_address": {"type": str}, + "version": {"type": int}, + "fast_leave": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Will be enabled automatically if evpn_l2_multicast is enabled.""" + source_address: str | None + """ + IPv4_address + If not set, IP address of "Loopback0" will be used. + """ + version: Literal[1, 2, 3] | None + """IGMP Version (By default EOS uses IGMP version 2 for IGMP querier).""" + fast_leave: bool | None + """Enable IGMP snooping fast-leave feature.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + source_address: str | None | UndefinedType = Undefined, + version: Literal[1, 2, 3] | None | UndefinedType = Undefined, + fast_leave: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IgmpSnoopingQuerier. + + + Subclass of AvdModel. + + Args: + enabled: Will be enabled automatically if evpn_l2_multicast is enabled. + source_address: + IPv4_address + If not set, IP address of "Loopback0" will be used. + version: IGMP Version (By default EOS uses IGMP version 2 for IGMP querier). + fast_leave: Enable IGMP snooping fast-leave feature. + _custom_data: _custom_data + + """ + + class Ospf(AvdModel): + """Subclass of AvdModel.""" + + class MessageDigestKeysItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "hash_algorithm": {"type": str, "default": "sha512"}, + "key": {"type": str}, + "_custom_data": {"type": dict}, + } + id: int | None + hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] + """Default value: `"sha512"`""" + key: str | None + """Type 7 encrypted key.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | None | UndefinedType = Undefined, + hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MessageDigestKeysItem. + + + Subclass of AvdModel. + + Args: + id: id + hash_algorithm: hash_algorithm + key: Type 7 encrypted key. + _custom_data: _custom_data + + """ + + class MessageDigestKeys(AvdList[MessageDigestKeysItem]): + """Subclass of AvdList with `MessageDigestKeysItem` items.""" + + MessageDigestKeys._item_type = MessageDigestKeysItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "point_to_point": {"type": bool, "default": False}, + "area": {"type": str, "default": "0.0.0.0"}, + "cost": {"type": int}, + "authentication": {"type": str}, + "simple_auth_key": {"type": str}, + "message_digest_keys": {"type": MessageDigestKeys}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + point_to_point: bool + """Default value: `False`""" + area: str + """ + OSPF area ID. + + Default value: `"0.0.0.0"` + """ + cost: int | None + """OSPF link cost.""" + authentication: Literal["simple", "message-digest"] | None + simple_auth_key: str | None + """Password used with simple authentication.""" + message_digest_keys: MessageDigestKeys + """Subclass of AvdList with `MessageDigestKeysItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + point_to_point: bool | UndefinedType = Undefined, + area: str | UndefinedType = Undefined, + cost: int | None | UndefinedType = Undefined, + authentication: Literal["simple", "message-digest"] | None | UndefinedType = Undefined, + simple_auth_key: str | None | UndefinedType = Undefined, + message_digest_keys: MessageDigestKeys | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospf. + + + Subclass of AvdModel. + + Args: + enabled: enabled + point_to_point: point_to_point + area: OSPF area ID. + cost: OSPF link cost. + authentication: authentication + simple_auth_key: Password used with simple authentication. + message_digest_keys: Subclass of AvdList with `MessageDigestKeysItem` items. + _custom_data: _custom_data + + """ + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class StructuredConfig(EosCliConfigGen.RouterBgp.VlansItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "structured_config": {"type": StructuredConfig}, + "raw_eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + structured_config: StructuredConfig + """ + Structured configuration and EOS CLI commands rendered on router_bgp.vlans.[id=]. + This + configuration will not be applied to vlan aware bundles. + + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the Router BGP, VLAN definition in the final EOS configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + structured_config: StructuredConfig | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + structured_config: + Structured configuration and EOS CLI commands rendered on router_bgp.vlans.[id=]. + This + configuration will not be applied to vlan aware bundles. + + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the Router BGP, VLAN definition in the final EOS configuration. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "name": {"type": str}, + "profile": {"type": str}, + "tags": {"type": Tags, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "evpn_vlan_bundle": {"type": str}, + "nodes": {"type": Nodes}, + "enabled": {"type": bool}, + "description": {"type": str}, + "ip_address": {"type": str}, + "ipv6_address": {"type": str}, + "ipv6_enable": {"type": bool}, + "ip_address_virtual": {"type": str}, + "ipv6_address_virtuals": {"type": Ipv6AddressVirtuals}, + "ip_address_virtual_secondaries": {"type": IpAddressVirtualSecondaries}, + "ip_virtual_router_addresses": {"type": IpVirtualRouterAddresses}, + "ipv6_virtual_router_addresses": {"type": Ipv6VirtualRouterAddresses}, + "ipv4_acl_in": {"type": str}, + "ipv4_acl_out": {"type": str}, + "ip_helpers": {"type": IpHelpers}, + "vni_override": {"type": int}, + "rt_override": {"type": str}, + "rd_override": {"type": str}, + "trunk_groups": {"type": TrunkGroups}, + "evpn_l2_multicast": {"type": EvpnL2Multicast}, + "evpn_l3_multicast": {"type": EvpnL3Multicast}, + "igmp_snooping_enabled": {"type": bool}, + "igmp_snooping_querier": {"type": IgmpSnoopingQuerier}, + "vxlan": {"type": bool, "default": True}, + "spanning_tree_priority": {"type": int}, + "mtu": {"type": int}, + "ospf": {"type": Ospf}, + "bgp": {"type": Bgp}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "evpn_l2_multi_domain": {"type": bool}, + "_custom_data": {"type": dict}, + } + id: int + """SVI interface id and VLAN id.""" + name: str + """VLAN name.""" + profile: str | None + """ + SVI profile name to apply. + SVI can refer to one svi_profile which again can refer to another + svi_profile to inherit settings in up to two levels (svi -> svi_profile -> svi_parent_profile). + """ + tags: Tags + """ + Tags leveraged for networks services filtering. + Tags are matched against "filter.tags" defined under + node type settings. + Tags are also matched against the "node_group" name under node type settings. + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + evpn_vlan_bundle: str | None + """ + Name of a bundle defined under 'evpn_vlan_bundles' to inherit configuration. + This setting overrides + "evpn_vlan_bundle" set at tenant level. + The common option "evpn_vlan_aware_bundles" is disregarded + for this option. + """ + nodes: Nodes + """ + Define node specific configuration, such as unique IP addresses. + Any keys set here will be merged + onto the SVI config, except `structured_config` keys which will replace the `structured_config` set + on SVI level. + + + Subclass of AvdIndexedList with `NodesItem` items. Primary key is `node` (`str`). + """ + enabled: bool | None + """Enable or disable interface.""" + description: str | None + """SVI description. By default set to VLAN name.""" + ip_address: str | None + """IPv4_address/Mask. Usually set under "nodes" to have unique IPv4 addresses per node.""" + ipv6_address: str | None + """IPv6_address/Mask. Usually set under "nodes" to have unique IPv6 addresses per node.""" + ipv6_enable: bool | None + """Explicitly enable/disable link-local IPv6 addressing.""" + ip_address_virtual: str | None + """ + IPv4_address/Mask. + IPv4 VXLAN Anycast IP address. + Conserves IP addresses in VXLAN deployments as it + doesn't require unique IP addresses on each node. + """ + ipv6_address_virtuals: Ipv6AddressVirtuals + """ + IPv6 VXLAN Anycast IP addresses. + Conserves IPv6 addresses in VXLAN deployments as it doesn't require + unique IPv6 addresses on each node. + + + Subclass of AvdList with `str` items. + """ + ip_address_virtual_secondaries: IpAddressVirtualSecondaries + """ + Secondary IPv4 VXLAN Anycast IP addresses. + + Subclass of AvdList with `str` items. + """ + ip_virtual_router_addresses: IpVirtualRouterAddresses + """ + IPv4 VARP addresses. + Requires an IP address to be configured on the SVI. + If ip_address_virtual is + also set, ip_virtual_router_addresses will take precedence + _if_ there is an ip_address configured + for the node. + + + Subclass of AvdList with `str` items. + """ + ipv6_virtual_router_addresses: Ipv6VirtualRouterAddresses + """ + IPv6 VARP addresses. + Requires an IPv6 address to be configured on the SVI. + If ipv6_address_virtuals + is also set, ipv6_virtual_router_addresses will take precedence + _if_ there is an ipv6_address + configured for the node. + + + Subclass of AvdList with `str` items. + """ + ipv4_acl_in: str | None + """ + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports substitution of the field "interface_ip". + """ + ipv4_acl_out: str | None + """ + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports substitution of the field "interface_ip". + """ + ip_helpers: IpHelpers + """ + IP helper for DHCP relay. + + Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is + `ip_helper` (`str`). + """ + vni_override: int | None + """ + By default the VNI will be derived from "mac_vrf_vni_base". + The vni_override allows us to override + this value and statically define it (optional). + """ + rt_override: str | None + """ + By default the MAC VRF RT will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rt_override will default to vni_override if set. + rt_override supports two formats: + - A single number which will be used in the RT fields instead of + mac_vrf_id/mac_vrf_vni (see 'overlay_rt_type' for details). + - A full RT string with colon + separator which will override the full RT. + """ + rd_override: str | None + """ + By default the MAC VRF RD will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rd_override will default to rt_override or + vni_override if set. + + rd_override supports two formats: + - A single number which will be used in + the RD assigned number field instead of mac_vrf_id/mac_vrf_vni (see 'overlay_rd_type' for details). + - A full RD string with colon separator which will override the full RD. + """ + trunk_groups: TrunkGroups + """Subclass of AvdList with `str` items.""" + evpn_l2_multicast: EvpnL2Multicast + """ + Explicitly enable or disable evpn_l2_multicast to override setting of + `.[].evpn_l2_multicast.enabled`. + When evpn_l2_multicast.enabled is set to true + for a vlan or a tenant, "igmp snooping" and "igmp snooping querier" will always be enabled, + overriding those individual settings. + Requires `evpn_multicast` to also be set to `true`. + + + Subclass + of AvdModel. + """ + evpn_l3_multicast: EvpnL3Multicast + """ + Explicitly enable or disable evpn_l3_multicast to override setting of + `.[].evpn_l3_multicast.enabled` and + `.[].vrfs.[].evpn_l3_multicast.enabled`. + Requires `evpn_multicast` to also be + set to `true`. + + + Subclass of AvdModel. + """ + igmp_snooping_enabled: bool | None + """Enable or disable IGMP snooping (Enabled by default on EOS).""" + igmp_snooping_querier: IgmpSnoopingQuerier + """Subclass of AvdModel.""" + vxlan: bool + """ + Extend this SVI over VXLAN. + + Default value: `True` + """ + spanning_tree_priority: int | None + """ + Setting spanning-tree priority per VLAN is only supported with `spanning_tree_mode: rapid-pvst` + under node type settings. + The default priority for rapid-PVST is set under the node type settings + with `spanning_tree_priority` (default=32768). + """ + mtu: int | None + """Interface MTU.""" + ospf: Ospf + """ + OSPF interface configuration. + + Subclass of AvdModel. + """ + bgp: Bgp + """Subclass of AvdModel.""" + raw_eos_cli: str | None + """EOS CLI rendered directly on the VLAN interface in the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config added under vlan_interfaces.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + """ + evpn_l2_multi_domain: bool | None + """ + Explicitly extend SVI to remote EVPN domains. + Overrides + `[].evpn_l2_multi_domain` and + `[].vrfs[].evpn_l2_multi_domain`. + Not supported in conjunction with EVPN vlan + aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` + or `[].vrfs[].svis[].evpn_vlan_bundle`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + profile: str | None | UndefinedType = Undefined, + tags: Tags | UndefinedType = Undefined, + evpn_vlan_bundle: str | None | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + enabled: bool | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + ipv6_address: str | None | UndefinedType = Undefined, + ipv6_enable: bool | None | UndefinedType = Undefined, + ip_address_virtual: str | None | UndefinedType = Undefined, + ipv6_address_virtuals: Ipv6AddressVirtuals | UndefinedType = Undefined, + ip_address_virtual_secondaries: IpAddressVirtualSecondaries | UndefinedType = Undefined, + ip_virtual_router_addresses: IpVirtualRouterAddresses | UndefinedType = Undefined, + ipv6_virtual_router_addresses: Ipv6VirtualRouterAddresses | UndefinedType = Undefined, + ipv4_acl_in: str | None | UndefinedType = Undefined, + ipv4_acl_out: str | None | UndefinedType = Undefined, + ip_helpers: IpHelpers | UndefinedType = Undefined, + vni_override: int | None | UndefinedType = Undefined, + rt_override: str | None | UndefinedType = Undefined, + rd_override: str | None | UndefinedType = Undefined, + trunk_groups: TrunkGroups | UndefinedType = Undefined, + evpn_l2_multicast: EvpnL2Multicast | UndefinedType = Undefined, + evpn_l3_multicast: EvpnL3Multicast | UndefinedType = Undefined, + igmp_snooping_enabled: bool | None | UndefinedType = Undefined, + igmp_snooping_querier: IgmpSnoopingQuerier | UndefinedType = Undefined, + vxlan: bool | UndefinedType = Undefined, + spanning_tree_priority: int | None | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + ospf: Ospf | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + evpn_l2_multi_domain: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SvisItem. + + + Subclass of AvdModel. + + Args: + id: SVI interface id and VLAN id. + name: VLAN name. + profile: + SVI profile name to apply. + SVI can refer to one svi_profile which again can refer to another + svi_profile to inherit settings in up to two levels (svi -> svi_profile -> svi_parent_profile). + tags: + Tags leveraged for networks services filtering. + Tags are matched against "filter.tags" defined under + node type settings. + Tags are also matched against the "node_group" name under node type settings. + Subclass of AvdList with `str` items. + evpn_vlan_bundle: + Name of a bundle defined under 'evpn_vlan_bundles' to inherit configuration. + This setting overrides + "evpn_vlan_bundle" set at tenant level. + The common option "evpn_vlan_aware_bundles" is disregarded + for this option. + nodes: + Define node specific configuration, such as unique IP addresses. + Any keys set here will be merged + onto the SVI config, except `structured_config` keys which will replace the `structured_config` set + on SVI level. + + + Subclass of AvdIndexedList with `NodesItem` items. Primary key is `node` (`str`). + enabled: Enable or disable interface. + description: SVI description. By default set to VLAN name. + ip_address: IPv4_address/Mask. Usually set under "nodes" to have unique IPv4 addresses per node. + ipv6_address: IPv6_address/Mask. Usually set under "nodes" to have unique IPv6 addresses per node. + ipv6_enable: Explicitly enable/disable link-local IPv6 addressing. + ip_address_virtual: + IPv4_address/Mask. + IPv4 VXLAN Anycast IP address. + Conserves IP addresses in VXLAN deployments as it + doesn't require unique IP addresses on each node. + ipv6_address_virtuals: + IPv6 VXLAN Anycast IP addresses. + Conserves IPv6 addresses in VXLAN deployments as it doesn't require + unique IPv6 addresses on each node. + + + Subclass of AvdList with `str` items. + ip_address_virtual_secondaries: + Secondary IPv4 VXLAN Anycast IP addresses. + + Subclass of AvdList with `str` items. + ip_virtual_router_addresses: + IPv4 VARP addresses. + Requires an IP address to be configured on the SVI. + If ip_address_virtual is + also set, ip_virtual_router_addresses will take precedence + _if_ there is an ip_address configured + for the node. + + + Subclass of AvdList with `str` items. + ipv6_virtual_router_addresses: + IPv6 VARP addresses. + Requires an IPv6 address to be configured on the SVI. + If ipv6_address_virtuals + is also set, ipv6_virtual_router_addresses will take precedence + _if_ there is an ipv6_address + configured for the node. + + + Subclass of AvdList with `str` items. + ipv4_acl_in: + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports substitution of the field "interface_ip". + ipv4_acl_out: + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports substitution of the field "interface_ip". + ip_helpers: + IP helper for DHCP relay. + + Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is + `ip_helper` (`str`). + vni_override: + By default the VNI will be derived from "mac_vrf_vni_base". + The vni_override allows us to override + this value and statically define it (optional). + rt_override: + By default the MAC VRF RT will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rt_override will default to vni_override if set. + rt_override supports two formats: + - A single number which will be used in the RT fields instead of + mac_vrf_id/mac_vrf_vni (see 'overlay_rt_type' for details). + - A full RT string with colon + separator which will override the full RT. + rd_override: + By default the MAC VRF RD will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rd_override will default to rt_override or + vni_override if set. + + rd_override supports two formats: + - A single number which will be used in + the RD assigned number field instead of mac_vrf_id/mac_vrf_vni (see 'overlay_rd_type' for details). + - A full RD string with colon separator which will override the full RD. + trunk_groups: Subclass of AvdList with `str` items. + evpn_l2_multicast: + Explicitly enable or disable evpn_l2_multicast to override setting of + `.[].evpn_l2_multicast.enabled`. + When evpn_l2_multicast.enabled is set to true + for a vlan or a tenant, "igmp snooping" and "igmp snooping querier" will always be enabled, + overriding those individual settings. + Requires `evpn_multicast` to also be set to `true`. + + + Subclass + of AvdModel. + evpn_l3_multicast: + Explicitly enable or disable evpn_l3_multicast to override setting of + `.[].evpn_l3_multicast.enabled` and + `.[].vrfs.[].evpn_l3_multicast.enabled`. + Requires `evpn_multicast` to also be + set to `true`. + + + Subclass of AvdModel. + igmp_snooping_enabled: Enable or disable IGMP snooping (Enabled by default on EOS). + igmp_snooping_querier: Subclass of AvdModel. + vxlan: Extend this SVI over VXLAN. + spanning_tree_priority: + Setting spanning-tree priority per VLAN is only supported with `spanning_tree_mode: rapid-pvst` + under node type settings. + The default priority for rapid-PVST is set under the node type settings + with `spanning_tree_priority` (default=32768). + mtu: Interface MTU. + ospf: + OSPF interface configuration. + + Subclass of AvdModel. + bgp: Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the VLAN interface in the final EOS configuration. + structured_config: + Custom structured config added under vlan_interfaces.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + evpn_l2_multi_domain: + Explicitly extend SVI to remote EVPN domains. + Overrides + `[].evpn_l2_multi_domain` and + `[].vrfs[].evpn_l2_multi_domain`. + Not supported in conjunction with EVPN vlan + aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` + or `[].vrfs[].svis[].evpn_vlan_bundle`. + _custom_data: _custom_data + + """ + + class Svis(AvdList[SvisItem]): + """Subclass of AvdList with `SvisItem` items.""" + + Svis._item_type = SvisItem + + class L3InterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Interfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Interfaces._item_type = str + + class EncapsulationDot1qVlan(AvdList[int]): + """Subclass of AvdList with `int` items.""" + + EncapsulationDot1qVlan._item_type = int + + class IpAddresses(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + IpAddresses._item_type = str + + class Nodes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Nodes._item_type = str + + class Descriptions(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Descriptions._item_type = str + + class Ospf(AvdModel): + """Subclass of AvdModel.""" + + class MessageDigestKeysItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "hash_algorithm": {"type": str, "default": "sha512"}, + "key": {"type": str}, + "_custom_data": {"type": dict}, + } + id: int | None + hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] + """Default value: `"sha512"`""" + key: str | None + """Key password.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | None | UndefinedType = Undefined, + hash_algorithm: Literal["md5", "sha1", "sha256", "sha384", "sha512"] | UndefinedType = Undefined, + key: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MessageDigestKeysItem. + + + Subclass of AvdModel. + + Args: + id: id + hash_algorithm: hash_algorithm + key: Key password. + _custom_data: _custom_data + + """ + + class MessageDigestKeys(AvdList[MessageDigestKeysItem]): + """Subclass of AvdList with `MessageDigestKeysItem` items.""" + + MessageDigestKeys._item_type = MessageDigestKeysItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "point_to_point": {"type": bool, "default": False}, + "area": {"type": str, "default": "0.0.0.0"}, + "cost": {"type": int}, + "authentication": {"type": str}, + "simple_auth_key": {"type": str}, + "message_digest_keys": {"type": MessageDigestKeys}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + point_to_point: bool + """Default value: `False`""" + area: str + """ + OSPF area ID. + + Default value: `"0.0.0.0"` + """ + cost: int | None + """OSPF link cost.""" + authentication: Literal["simple", "message-digest"] | None + simple_auth_key: str | None + """Password used with simple authentication.""" + message_digest_keys: MessageDigestKeys + """Subclass of AvdList with `MessageDigestKeysItem` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + point_to_point: bool | UndefinedType = Undefined, + area: str | UndefinedType = Undefined, + cost: int | None | UndefinedType = Undefined, + authentication: Literal["simple", "message-digest"] | None | UndefinedType = Undefined, + simple_auth_key: str | None | UndefinedType = Undefined, + message_digest_keys: MessageDigestKeys | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospf. + + + Subclass of AvdModel. + + Args: + enabled: enabled + point_to_point: point_to_point + area: OSPF area ID. + cost: OSPF link cost. + authentication: authentication + simple_auth_key: Password used with simple authentication. + message_digest_keys: Subclass of AvdList with `MessageDigestKeysItem` items. + _custom_data: _custom_data + + """ + + class Pim(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, enabled: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + Pim. + + + Subclass of AvdModel. + + Args: + enabled: enabled + _custom_data: _custom_data + + """ + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "interfaces": {"type": Interfaces}, + "encapsulation_dot1q_vlan": {"type": EncapsulationDot1qVlan}, + "ip_addresses": {"type": IpAddresses}, + "nodes": {"type": Nodes}, + "description": {"type": str}, + "descriptions": {"type": Descriptions}, + "enabled": {"type": bool, "default": True}, + "mtu": {"type": int}, + "ipv4_acl_in": {"type": str}, + "ipv4_acl_out": {"type": str}, + "ospf": {"type": Ospf}, + "pim": {"type": Pim}, + "flow_tracking": {"type": FlowTracking}, + "structured_config": {"type": StructuredConfig}, + "raw_eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + interfaces: Interfaces + """Subclass of AvdList with `str` items.""" + encapsulation_dot1q_vlan: EncapsulationDot1qVlan + """ + For sub-interfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + + Subclass of AvdList with `int` items. + """ + ip_addresses: IpAddresses + """Subclass of AvdList with `str` items.""" + nodes: Nodes + """Subclass of AvdList with `str` items.""" + description: str | None + descriptions: Descriptions + """ + "descriptions" has precedence over "description". + + + Subclass of AvdList with `str` items. + """ + enabled: bool + """Default value: `True`""" + mtu: int | None + ipv4_acl_in: str | None + ipv4_acl_out: str | None + ospf: Ospf + """ + OSPF interface configuration. + + Subclass of AvdModel. + """ + pim: Pim + """ + Enable PIM sparse-mode on the interface; requires "evpn_l3_multicast" to be enabled on the + VRF/Tenant. + Enabling this implicitly makes the device a PIM External Gateway (PEG) in EVPN designs + only. + At least one RP address must be configured for EVPN PEG to be configured. + + + Subclass of + AvdModel. + """ + flow_tracking: FlowTracking + """ + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + """ + structured_config: StructuredConfig + """ + Custom structured config added under ethernet_interfaces.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the Ethernet interface in the final EOS configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interfaces: Interfaces | UndefinedType = Undefined, + encapsulation_dot1q_vlan: EncapsulationDot1qVlan | UndefinedType = Undefined, + ip_addresses: IpAddresses | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + descriptions: Descriptions | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + mtu: int | None | UndefinedType = Undefined, + ipv4_acl_in: str | None | UndefinedType = Undefined, + ipv4_acl_out: str | None | UndefinedType = Undefined, + ospf: Ospf | UndefinedType = Undefined, + pim: Pim | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L3InterfacesItem. + + + Subclass of AvdModel. + + Args: + interfaces: Subclass of AvdList with `str` items. + encapsulation_dot1q_vlan: + For sub-interfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + + Subclass of AvdList with `int` items. + ip_addresses: Subclass of AvdList with `str` items. + nodes: Subclass of AvdList with `str` items. + description: description + descriptions: + "descriptions" has precedence over "description". + + + Subclass of AvdList with `str` items. + enabled: enabled + mtu: mtu + ipv4_acl_in: ipv4_acl_in + ipv4_acl_out: ipv4_acl_out + ospf: + OSPF interface configuration. + + Subclass of AvdModel. + pim: + Enable PIM sparse-mode on the interface; requires "evpn_l3_multicast" to be enabled on the + VRF/Tenant. + Enabling this implicitly makes the device a PIM External Gateway (PEG) in EVPN designs + only. + At least one RP address must be configured for EVPN PEG to be configured. + + + Subclass of + AvdModel. + flow_tracking: + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + structured_config: + Custom structured config added under ethernet_interfaces.[name=] for eos_cli_config_gen. + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the Ethernet interface in the final EOS configuration. + _custom_data: _custom_data + + """ + + class L3Interfaces(AvdList[L3InterfacesItem]): + """Subclass of AvdList with `L3InterfacesItem` items.""" + + L3Interfaces._item_type = L3InterfacesItem + + class LoopbacksItem(AvdModel): + """Subclass of AvdModel.""" + + class Ospf(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "area": {"type": str, "default": "0.0.0.0"}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + area: str + """ + OSPF area ID. + + Default value: `"0.0.0.0"` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + area: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ospf. + + + Subclass of AvdModel. + + Args: + enabled: enabled + area: OSPF area ID. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "node": {"type": str}, + "loopback": {"type": int}, + "ip_address": {"type": str}, + "description": {"type": str}, + "enabled": {"type": bool, "default": True}, + "ospf": {"type": Ospf}, + "raw_eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + node: str + loopback: int + ip_address: str + description: str | None + enabled: bool + """Default value: `True`""" + ospf: Ospf + """ + OSPF interface configuration. + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the Loopback interface in the final EOS configuration.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + node: str | UndefinedType = Undefined, + loopback: int | UndefinedType = Undefined, + ip_address: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + ospf: Ospf | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LoopbacksItem. + + + Subclass of AvdModel. + + Args: + node: node + loopback: loopback + ip_address: ip_address + description: description + enabled: enabled + ospf: + OSPF interface configuration. + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the Loopback interface in the final EOS configuration. + _custom_data: _custom_data + + """ + + class Loopbacks(AvdList[LoopbacksItem]): + """Subclass of AvdList with `LoopbacksItem` items.""" + + Loopbacks._item_type = LoopbacksItem + + class StaticRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + class Nodes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Nodes._item_type = str + + _fields: ClassVar[dict] = { + "destination_address_prefix": {"type": str}, + "gateway": {"type": str}, + "track_bfd": {"type": bool}, + "distance": {"type": int}, + "tag": {"type": int}, + "name": {"type": str}, + "metric": {"type": int}, + "interface": {"type": str}, + "nodes": {"type": Nodes}, + "_custom_data": {"type": dict}, + } + destination_address_prefix: str | None + """IPv4_address.""" + gateway: str | None + """IPv4_address.""" + track_bfd: bool | None + """Track next-hop using BFD.""" + distance: int | None + tag: int | None + name: str | None + """description.""" + metric: int | None + interface: str | None + nodes: Nodes + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + destination_address_prefix: str | None | UndefinedType = Undefined, + gateway: str | None | UndefinedType = Undefined, + track_bfd: bool | None | UndefinedType = Undefined, + distance: int | None | UndefinedType = Undefined, + tag: int | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + metric: int | None | UndefinedType = Undefined, + interface: str | None | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + StaticRoutesItem. + + + Subclass of AvdModel. + + Args: + destination_address_prefix: IPv4_address. + gateway: IPv4_address. + track_bfd: Track next-hop using BFD. + distance: distance + tag: tag + name: description. + metric: metric + interface: interface + nodes: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class StaticRoutes(AvdList[StaticRoutesItem]): + """Subclass of AvdList with `StaticRoutesItem` items.""" + + StaticRoutes._item_type = StaticRoutesItem + + class Ipv6StaticRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + class Nodes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Nodes._item_type = str + + _fields: ClassVar[dict] = { + "destination_address_prefix": {"type": str}, + "gateway": {"type": str}, + "track_bfd": {"type": bool}, + "distance": {"type": int}, + "tag": {"type": int}, + "name": {"type": str}, + "metric": {"type": int}, + "interface": {"type": str}, + "nodes": {"type": Nodes}, + "_custom_data": {"type": dict}, + } + destination_address_prefix: str | None + """IPv6_address.""" + gateway: str | None + track_bfd: bool | None + """Track next-hop using BFD.""" + distance: int | None + tag: int | None + name: str | None + """description.""" + metric: int | None + interface: str | None + nodes: Nodes + """Subclass of AvdList with `str` items.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + destination_address_prefix: str | None | UndefinedType = Undefined, + gateway: str | None | UndefinedType = Undefined, + track_bfd: bool | None | UndefinedType = Undefined, + distance: int | None | UndefinedType = Undefined, + tag: int | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + metric: int | None | UndefinedType = Undefined, + interface: str | None | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ipv6StaticRoutesItem. + + + Subclass of AvdModel. + + Args: + destination_address_prefix: IPv6_address. + gateway: gateway + track_bfd: Track next-hop using BFD. + distance: distance + tag: tag + name: description. + metric: metric + interface: interface + nodes: Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class Ipv6StaticRoutes(AvdList[Ipv6StaticRoutesItem]): + """Subclass of AvdList with `Ipv6StaticRoutesItem` items.""" + + Ipv6StaticRoutes._item_type = Ipv6StaticRoutesItem + + class BgpPeersItem(AvdModel): + """Subclass of AvdModel.""" + + class DefaultOriginate(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"always": {"type": bool}, "_custom_data": {"type": dict}} + always: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, always: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + DefaultOriginate. + + + Subclass of AvdModel. + + Args: + always: always + _custom_data: _custom_data + + """ + + class Nodes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Nodes._item_type = str + + _fields: ClassVar[dict] = { + "ip_address": {"type": str}, + "peer_group": {"type": str}, + "remote_as": {"type": str}, + "description": {"type": str}, + "password": {"type": str}, + "send_community": {"type": str}, + "next_hop_self": {"type": bool}, + "timers": {"type": str}, + "maximum_routes": {"type": int}, + "maximum_routes_warning_only": {"type": bool}, + "default_originate": {"type": DefaultOriginate}, + "update_source": {"type": str}, + "ebgp_multihop": {"type": int}, + "nodes": {"type": Nodes}, + "set_ipv4_next_hop": {"type": str}, + "set_ipv6_next_hop": {"type": str}, + "route_map_out": {"type": str}, + "route_map_in": {"type": str}, + "prefix_list_in": {"type": str}, + "prefix_list_out": {"type": str}, + "local_as": {"type": str}, + "weight": {"type": int}, + "bfd": {"type": bool}, + "shutdown": {"type": bool}, + "_custom_data": {"type": dict}, + } + ip_address: str + """IPv4_address or IPv6_address.""" + peer_group: str | None + """Peer group name.""" + remote_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + description: str | None + password: str | None + """Encrypted password.""" + send_community: str | None + """'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'.""" + next_hop_self: bool | None + timers: str | None + """BGP Keepalive and Hold Timer values in seconds as string <0-3600> <0-3600>.""" + maximum_routes: int | None + """Maximum number of routes (0 means unlimited).""" + maximum_routes_warning_only: bool | None + default_originate: DefaultOriginate + """Subclass of AvdModel.""" + update_source: str | None + ebgp_multihop: int | None + """Time-to-live in range of hops.""" + nodes: Nodes + """ + Nodes is required to restrict configuration of BGP neighbors to certain nodes in the network. + Subclass of AvdList with `str` items. + """ + set_ipv4_next_hop: str | None + """ + IPv4_address + Next hop settings can be either ipv4 or ipv6 for one neighbor, this will be applied by + a uniquely generated route-map per neighbor. + Next hop takes precedence over route_map_out. + """ + set_ipv6_next_hop: str | None + """ + IPv6_address + Next hop settings can be either ipv4 or ipv6 for one neighbor, this will be applied by + a uniquely generated route-map per neighbor. + Next hop takes precedence over route_map_out. + """ + route_map_out: str | None + """Route-map name.""" + route_map_in: str | None + """Route-map name.""" + prefix_list_in: str | None + """ + Inbound prefix list name. + The prefix-list will be associated under the IPv4 or IPv6 address family + based on the IP address. + """ + prefix_list_out: str | None + """ + Outbound prefix list name. + The prefix-list will be associated under the IPv4 or IPv6 address family + based on the IP address. + """ + local_as: str | None + """ + Local BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation + in YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + weight: int | None + bfd: bool | None + shutdown: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ip_address: str | UndefinedType = Undefined, + peer_group: str | None | UndefinedType = Undefined, + remote_as: str | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + password: str | None | UndefinedType = Undefined, + send_community: str | None | UndefinedType = Undefined, + next_hop_self: bool | None | UndefinedType = Undefined, + timers: str | None | UndefinedType = Undefined, + maximum_routes: int | None | UndefinedType = Undefined, + maximum_routes_warning_only: bool | None | UndefinedType = Undefined, + default_originate: DefaultOriginate | UndefinedType = Undefined, + update_source: str | None | UndefinedType = Undefined, + ebgp_multihop: int | None | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + set_ipv4_next_hop: str | None | UndefinedType = Undefined, + set_ipv6_next_hop: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + prefix_list_in: str | None | UndefinedType = Undefined, + prefix_list_out: str | None | UndefinedType = Undefined, + local_as: str | None | UndefinedType = Undefined, + weight: int | None | UndefinedType = Undefined, + bfd: bool | None | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BgpPeersItem. + + + Subclass of AvdModel. + + Args: + ip_address: IPv4_address or IPv6_address. + peer_group: Peer group name. + remote_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + description: description + password: Encrypted password. + send_community: 'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'. + next_hop_self: next_hop_self + timers: BGP Keepalive and Hold Timer values in seconds as string <0-3600> <0-3600>. + maximum_routes: Maximum number of routes (0 means unlimited). + maximum_routes_warning_only: maximum_routes_warning_only + default_originate: Subclass of AvdModel. + update_source: update_source + ebgp_multihop: Time-to-live in range of hops. + nodes: + Nodes is required to restrict configuration of BGP neighbors to certain nodes in the network. + Subclass of AvdList with `str` items. + set_ipv4_next_hop: + IPv4_address + Next hop settings can be either ipv4 or ipv6 for one neighbor, this will be applied by + a uniquely generated route-map per neighbor. + Next hop takes precedence over route_map_out. + set_ipv6_next_hop: + IPv6_address + Next hop settings can be either ipv4 or ipv6 for one neighbor, this will be applied by + a uniquely generated route-map per neighbor. + Next hop takes precedence over route_map_out. + route_map_out: Route-map name. + route_map_in: Route-map name. + prefix_list_in: + Inbound prefix list name. + The prefix-list will be associated under the IPv4 or IPv6 address family + based on the IP address. + prefix_list_out: + Outbound prefix list name. + The prefix-list will be associated under the IPv4 or IPv6 address family + based on the IP address. + local_as: + Local BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation + in YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + weight: weight + bfd: bfd + shutdown: shutdown + _custom_data: _custom_data + + """ + + class BgpPeers(AvdList[BgpPeersItem]): + """Subclass of AvdList with `BgpPeersItem` items.""" + + BgpPeers._item_type = BgpPeersItem + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class StructuredConfig(EosCliConfigGen.RouterBgp.VrfsItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """ + Force (no) configuration of BGP for the VRF. + If not set, BGP will be configured when needed + according to the following rules: + - If the VRF is part of an overlay (`evpn` or `mpls`), BGP will be + configured for it. + - If any BGP peers are configured under the VRF, BGP will be configured for it. + This is useful for L2LS designs with VRFs. + - If uplink type is `p2p-vrfs` *and* the vrf is included + in the uplink VRFs, BGP will be configured for it. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the Router BGP, VRF definition in the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config added under router_bgp.vrfs.[name=] for eos_cli_config_gen. + + Subclass + of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + enabled: + Force (no) configuration of BGP for the VRF. + If not set, BGP will be configured when needed + according to the following rules: + - If the VRF is part of an overlay (`evpn` or `mpls`), BGP will be + configured for it. + - If any BGP peers are configured under the VRF, BGP will be configured for it. + This is useful for L2LS designs with VRFs. + - If uplink type is `p2p-vrfs` *and* the vrf is included + in the uplink VRFs, BGP will be configured for it. + raw_eos_cli: EOS CLI rendered directly on the Router BGP, VRF definition in the final EOS configuration. + structured_config: + Custom structured config added under router_bgp.vrfs.[name=] for eos_cli_config_gen. + + Subclass + of AvdModel. + _custom_data: _custom_data + + """ + + class BgpPeerGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class Nodes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Nodes._item_type = str + + class AddressFamilyIpv4(AvdModel): + """Subclass of AvdModel.""" + + class DefaultOriginate(EosCliConfigGen.RouterBgp.AddressFamilyIpv4.PeerGroupsItem.DefaultOriginate): + """Subclass of AvdModel.""" + + class NextHop(EosCliConfigGen.RouterBgp.AddressFamilyIpv4.PeerGroupsItem.NextHop): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "default_originate": {"type": DefaultOriginate}, + "next_hop": {"type": NextHop}, + "prefix_list_in": {"type": str}, + "prefix_list_out": {"type": str}, + "_custom_data": {"type": dict}, + } + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + default_originate: DefaultOriginate + """Subclass of AvdModel.""" + next_hop: NextHop + """Subclass of AvdModel.""" + prefix_list_in: str | None + """Inbound prefix-list name.""" + prefix_list_out: str | None + """Outbound prefix-list name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + default_originate: DefaultOriginate | UndefinedType = Undefined, + next_hop: NextHop | UndefinedType = Undefined, + prefix_list_in: str | None | UndefinedType = Undefined, + prefix_list_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv4. + + + Subclass of AvdModel. + + Args: + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + default_originate: Subclass of AvdModel. + next_hop: Subclass of AvdModel. + prefix_list_in: Inbound prefix-list name. + prefix_list_out: Outbound prefix-list name. + _custom_data: _custom_data + + """ + + class AddressFamilyIpv6(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "activate": {"type": bool}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "prefix_list_in": {"type": str}, + "prefix_list_out": {"type": str}, + "_custom_data": {"type": dict}, + } + activate: bool | None + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + prefix_list_in: str | None + """Inbound prefix-list name.""" + prefix_list_out: str | None + """Outbound prefix-list name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + activate: bool | None | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + prefix_list_in: str | None | UndefinedType = Undefined, + prefix_list_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AddressFamilyIpv6. + + + Subclass of AvdModel. + + Args: + activate: activate + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + prefix_list_in: Inbound prefix-list name. + prefix_list_out: Outbound prefix-list name. + _custom_data: _custom_data + + """ + + class AsPath(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "remote_as_replace_out": {"type": bool}, + "prepend_own_disabled": {"type": bool}, + "_custom_data": {"type": dict}, + } + remote_as_replace_out: bool | None + """Replace AS number with local AS number.""" + prepend_own_disabled: bool | None + """Disable prepending own AS number to AS path.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + remote_as_replace_out: bool | None | UndefinedType = Undefined, + prepend_own_disabled: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AsPath. + + + Subclass of AvdModel. + + Args: + remote_as_replace_out: Replace AS number with local AS number. + prepend_own_disabled: Disable prepending own AS number to AS path. + _custom_data: _custom_data + + """ + + class RemovePrivateAs(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "all": {"type": bool}, + "replace_as": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + all: bool | None + replace_as: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + all: bool | None | UndefinedType = Undefined, + replace_as: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemovePrivateAs. + + + Subclass of AvdModel. + + Args: + enabled: enabled + all: all + replace_as: replace_as + _custom_data: _custom_data + + """ + + class RemovePrivateAsIngress(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "replace_as": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + replace_as: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + replace_as: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemovePrivateAsIngress. + + + Subclass of AvdModel. + + Args: + enabled: enabled + replace_as: replace_as + _custom_data: _custom_data + + """ + + class BfdTimers(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "interval": {"type": int}, + "min_rx": {"type": int}, + "multiplier": {"type": int}, + "_custom_data": {"type": dict}, + } + interval: int + """Interval in milliseconds.""" + min_rx: int + """Rate in milliseconds.""" + multiplier: int + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + interval: int | UndefinedType = Undefined, + min_rx: int | UndefinedType = Undefined, + multiplier: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BfdTimers. + + + Subclass of AvdModel. + + Args: + interval: Interval in milliseconds. + min_rx: Rate in milliseconds. + multiplier: multiplier + _custom_data: _custom_data + + """ + + class DefaultOriginate(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "always": {"type": bool}, + "route_map": {"type": str}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + always: bool | None + route_map: str | None + """Route-map name.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + always: bool | None | UndefinedType = Undefined, + route_map: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DefaultOriginate. + + + Subclass of AvdModel. + + Args: + enabled: enabled + always: always + route_map: Route-map name. + _custom_data: _custom_data + + """ + + class MissingPolicy(AvdModel): + """Subclass of AvdModel.""" + + class DirectionIn(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "action": {"type": str}, + "include_community_list": {"type": bool}, + "include_prefix_list": {"type": bool}, + "include_sub_route_map": {"type": bool}, + "_custom_data": {"type": dict}, + } + action: Literal["deny", "permit", "deny-in-out"] + """Missing policy action.""" + include_community_list: bool | None + """Include community-list references in missing policy decision.""" + include_prefix_list: bool | None + """Include prefix-list references in missing policy decision.""" + include_sub_route_map: bool | None + """Include sub-route-map references in missing policy decision.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["deny", "permit", "deny-in-out"] | UndefinedType = Undefined, + include_community_list: bool | None | UndefinedType = Undefined, + include_prefix_list: bool | None | UndefinedType = Undefined, + include_sub_route_map: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionIn. + + + Subclass of AvdModel. + + Args: + action: Missing policy action. + include_community_list: Include community-list references in missing policy decision. + include_prefix_list: Include prefix-list references in missing policy decision. + include_sub_route_map: Include sub-route-map references in missing policy decision. + _custom_data: _custom_data + + """ + + class DirectionOut(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "action": {"type": str}, + "include_community_list": {"type": bool}, + "include_prefix_list": {"type": bool}, + "include_sub_route_map": {"type": bool}, + "_custom_data": {"type": dict}, + } + action: Literal["deny", "permit", "deny-in-out"] + """Missing policy action.""" + include_community_list: bool | None + """Include community-list references in missing policy decision.""" + include_prefix_list: bool | None + """Include prefix-list references in missing policy decision.""" + include_sub_route_map: bool | None + """Include sub-route-map references in missing policy decision.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + action: Literal["deny", "permit", "deny-in-out"] | UndefinedType = Undefined, + include_community_list: bool | None | UndefinedType = Undefined, + include_prefix_list: bool | None | UndefinedType = Undefined, + include_sub_route_map: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DirectionOut. + + + Subclass of AvdModel. + + Args: + action: Missing policy action. + include_community_list: Include community-list references in missing policy decision. + include_prefix_list: Include prefix-list references in missing policy decision. + include_sub_route_map: Include sub-route-map references in missing policy decision. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "direction_in": {"type": DirectionIn}, + "direction_out": {"type": DirectionOut}, + "_custom_data": {"type": dict}, + } + direction_in: DirectionIn + """ + Missing policy inbound direction. + + Subclass of AvdModel. + """ + direction_out: DirectionOut + """ + Missing policy outbound direction. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + direction_in: DirectionIn | UndefinedType = Undefined, + direction_out: DirectionOut | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingPolicy. + + + Subclass of AvdModel. + + Args: + direction_in: + Missing policy inbound direction. + + Subclass of AvdModel. + direction_out: + Missing policy outbound direction. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class LinkBandwidth(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "default": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + default: str | None + """nn.nn(K|M|G) link speed in bits/second.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + default: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkBandwidth. + + + Subclass of AvdModel. + + Args: + enabled: enabled + default: nn.nn(K|M|G) link speed in bits/second. + _custom_data: _custom_data + + """ + + class AllowasIn(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "times": {"type": int}, "_custom_data": {"type": dict}} + enabled: bool | None + times: int | None + """Number of local ASNs allowed in a BGP update.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + times: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AllowasIn. + + + Subclass of AvdModel. + + Args: + enabled: enabled + times: Number of local ASNs allowed in a BGP update. + _custom_data: _custom_data + + """ + + class RibInPrePolicyRetain(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "all": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + all: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + all: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RibInPrePolicyRetain. + + + Subclass of AvdModel. + + Args: + enabled: enabled + all: all + _custom_data: _custom_data + + """ + + class SharedSecret(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "hash_algorithm": {"type": str}, "_custom_data": {"type": dict}} + profile: str + """Name of profile defined under `management_security`.""" + hash_algorithm: Literal["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"] + """Note: Algorithm hmac-sha-256 requires EOS version 4.31.1F and above.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | UndefinedType = Undefined, + hash_algorithm: Literal["aes-128-cmac-96", "hmac-sha-256", "hmac-sha1-96"] | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SharedSecret. + + + Subclass of AvdModel. + + Args: + profile: Name of profile defined under `management_security`. + hash_algorithm: Note: Algorithm hmac-sha-256 requires EOS version 4.31.1F and above. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "nodes": {"type": Nodes}, + "address_family_ipv4": {"type": AddressFamilyIpv4}, + "address_family_ipv6": {"type": AddressFamilyIpv6}, + "type": {"type": str}, + "remote_as": {"type": str}, + "local_as": {"type": str}, + "description": {"type": str}, + "shutdown": {"type": bool}, + "as_path": {"type": AsPath}, + "remove_private_as": {"type": RemovePrivateAs}, + "remove_private_as_ingress": {"type": RemovePrivateAsIngress}, + "next_hop_unchanged": {"type": bool}, + "update_source": {"type": str}, + "route_reflector_client": {"type": bool}, + "bfd": {"type": bool}, + "bfd_timers": {"type": BfdTimers}, + "ebgp_multihop": {"type": int}, + "next_hop_self": {"type": bool}, + "password": {"type": str}, + "passive": {"type": bool}, + "default_originate": {"type": DefaultOriginate}, + "send_community": {"type": str}, + "maximum_routes": {"type": int}, + "maximum_routes_warning_limit": {"type": str}, + "maximum_routes_warning_only": {"type": bool}, + "missing_policy": {"type": MissingPolicy}, + "link_bandwidth": {"type": LinkBandwidth}, + "allowas_in": {"type": AllowasIn}, + "weight": {"type": int}, + "timers": {"type": str}, + "rib_in_pre_policy_retain": {"type": RibInPrePolicyRetain}, + "route_map_in": {"type": str}, + "route_map_out": {"type": str}, + "session_tracker": {"type": str}, + "shared_secret": {"type": SharedSecret}, + "ttl_maximum_hops": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str | None + """BGP peer group name.""" + nodes: Nodes + """ + Nodes is required to restrict configuration of BGP neighbors to certain nodes in the network. + If not + set the peer-group is created on devices which have a bgp_peer mapped to the corresponding + peer_group. + + + Subclass of AvdList with `str` items. + """ + address_family_ipv4: AddressFamilyIpv4 + """Subclass of AvdModel.""" + address_family_ipv6: AddressFamilyIpv6 + """Subclass of AvdModel.""" + type: str | None + """Key only used for documentation or validation purposes.""" + remote_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + local_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + description: str | None + shutdown: bool | None + as_path: AsPath + """ + BGP AS-PATH options. + + Subclass of AvdModel. + """ + remove_private_as: RemovePrivateAs + """ + Remove private AS numbers in outbound AS path. + + Subclass of AvdModel. + """ + remove_private_as_ingress: RemovePrivateAsIngress + """Subclass of AvdModel.""" + next_hop_unchanged: bool | None + update_source: str | None + """IP address or interface name.""" + route_reflector_client: bool | None + bfd: bool | None + """Enable BFD.""" + bfd_timers: BfdTimers + """ + Override default BFD timers. BFD must be enabled with `bfd: true`. + + Subclass of AvdModel. + """ + ebgp_multihop: int | None + """Time-to-live in range of hops.""" + next_hop_self: bool | None + password: str | None + passive: bool | None + default_originate: DefaultOriginate + """Subclass of AvdModel.""" + send_community: str | None + """'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'.""" + maximum_routes: int | None + """Maximum number of routes (0 means unlimited).""" + maximum_routes_warning_limit: str | None + """ + Maximum number of routes after which a warning is issued (0 means never warn) or + Percentage of + maximum number of routes at which to warn ("<1-100> percent"). + """ + maximum_routes_warning_only: bool | None + missing_policy: MissingPolicy + """ + Missing policy configuration for all address-families. + + Subclass of AvdModel. + """ + link_bandwidth: LinkBandwidth + """Subclass of AvdModel.""" + allowas_in: AllowasIn + """Subclass of AvdModel.""" + weight: int | None + timers: str | None + """BGP Keepalive and Hold Timer values in seconds as string "<0-3600> <0-3600>".""" + rib_in_pre_policy_retain: RibInPrePolicyRetain + """Subclass of AvdModel.""" + route_map_in: str | None + """Inbound route-map name.""" + route_map_out: str | None + """Outbound route-map name.""" + session_tracker: str | None + shared_secret: SharedSecret + """Subclass of AvdModel.""" + ttl_maximum_hops: int | None + """Maximum number of hops.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + address_family_ipv4: AddressFamilyIpv4 | UndefinedType = Undefined, + address_family_ipv6: AddressFamilyIpv6 | UndefinedType = Undefined, + type: str | None | UndefinedType = Undefined, + remote_as: str | None | UndefinedType = Undefined, + local_as: str | None | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + shutdown: bool | None | UndefinedType = Undefined, + as_path: AsPath | UndefinedType = Undefined, + remove_private_as: RemovePrivateAs | UndefinedType = Undefined, + remove_private_as_ingress: RemovePrivateAsIngress | UndefinedType = Undefined, + next_hop_unchanged: bool | None | UndefinedType = Undefined, + update_source: str | None | UndefinedType = Undefined, + route_reflector_client: bool | None | UndefinedType = Undefined, + bfd: bool | None | UndefinedType = Undefined, + bfd_timers: BfdTimers | UndefinedType = Undefined, + ebgp_multihop: int | None | UndefinedType = Undefined, + next_hop_self: bool | None | UndefinedType = Undefined, + password: str | None | UndefinedType = Undefined, + passive: bool | None | UndefinedType = Undefined, + default_originate: DefaultOriginate | UndefinedType = Undefined, + send_community: str | None | UndefinedType = Undefined, + maximum_routes: int | None | UndefinedType = Undefined, + maximum_routes_warning_limit: str | None | UndefinedType = Undefined, + maximum_routes_warning_only: bool | None | UndefinedType = Undefined, + missing_policy: MissingPolicy | UndefinedType = Undefined, + link_bandwidth: LinkBandwidth | UndefinedType = Undefined, + allowas_in: AllowasIn | UndefinedType = Undefined, + weight: int | None | UndefinedType = Undefined, + timers: str | None | UndefinedType = Undefined, + rib_in_pre_policy_retain: RibInPrePolicyRetain | UndefinedType = Undefined, + route_map_in: str | None | UndefinedType = Undefined, + route_map_out: str | None | UndefinedType = Undefined, + session_tracker: str | None | UndefinedType = Undefined, + shared_secret: SharedSecret | UndefinedType = Undefined, + ttl_maximum_hops: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + BgpPeerGroupsItem. + + + Subclass of AvdModel. + + Args: + name: BGP peer group name. + nodes: + Nodes is required to restrict configuration of BGP neighbors to certain nodes in the network. + If not + set the peer-group is created on devices which have a bgp_peer mapped to the corresponding + peer_group. + + + Subclass of AvdList with `str` items. + address_family_ipv4: Subclass of AvdModel. + address_family_ipv6: Subclass of AvdModel. + type: Key only used for documentation or validation purposes. + remote_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + local_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + description: description + shutdown: shutdown + as_path: + BGP AS-PATH options. + + Subclass of AvdModel. + remove_private_as: + Remove private AS numbers in outbound AS path. + + Subclass of AvdModel. + remove_private_as_ingress: Subclass of AvdModel. + next_hop_unchanged: next_hop_unchanged + update_source: IP address or interface name. + route_reflector_client: route_reflector_client + bfd: Enable BFD. + bfd_timers: + Override default BFD timers. BFD must be enabled with `bfd: true`. + + Subclass of AvdModel. + ebgp_multihop: Time-to-live in range of hops. + next_hop_self: next_hop_self + password: password + passive: passive + default_originate: Subclass of AvdModel. + send_community: 'all' or a combination of 'standard', 'extended', 'large' and 'link-bandwidth (w/options)'. + maximum_routes: Maximum number of routes (0 means unlimited). + maximum_routes_warning_limit: + Maximum number of routes after which a warning is issued (0 means never warn) or + Percentage of + maximum number of routes at which to warn ("<1-100> percent"). + maximum_routes_warning_only: maximum_routes_warning_only + missing_policy: + Missing policy configuration for all address-families. + + Subclass of AvdModel. + link_bandwidth: Subclass of AvdModel. + allowas_in: Subclass of AvdModel. + weight: weight + timers: BGP Keepalive and Hold Timer values in seconds as string "<0-3600> <0-3600>". + rib_in_pre_policy_retain: Subclass of AvdModel. + route_map_in: Inbound route-map name. + route_map_out: Outbound route-map name. + session_tracker: session_tracker + shared_secret: Subclass of AvdModel. + ttl_maximum_hops: Maximum number of hops. + _custom_data: _custom_data + + """ + + class BgpPeerGroups(AvdList[BgpPeerGroupsItem]): + """Subclass of AvdList with `BgpPeerGroupsItem` items.""" + + BgpPeerGroups._item_type = BgpPeerGroupsItem + + class AdditionalRouteTargetsItem(AvdModel): + """Subclass of AvdModel.""" + + class Nodes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Nodes._item_type = str + + _fields: ClassVar[dict] = { + "type": {"type": str}, + "address_family": {"type": str}, + "route_target": {"type": str}, + "nodes": {"type": Nodes}, + "_custom_data": {"type": dict}, + } + type: Literal["import", "export"] | None + address_family: str | None + route_target: str | None + nodes: Nodes + """ + Nodes is required to restrict configuration of BGP neighbors to certain nodes in the network. + Subclass of AvdList with `str` items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + type: Literal["import", "export"] | None | UndefinedType = Undefined, + address_family: str | None | UndefinedType = Undefined, + route_target: str | None | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + AdditionalRouteTargetsItem. + + + Subclass of AvdModel. + + Args: + type: type + address_family: address_family + route_target: route_target + nodes: + Nodes is required to restrict configuration of BGP neighbors to certain nodes in the network. + Subclass of AvdList with `str` items. + _custom_data: _custom_data + + """ + + class AdditionalRouteTargets(AvdList[AdditionalRouteTargetsItem]): + """Subclass of AvdList with `AdditionalRouteTargetsItem` items.""" + + AdditionalRouteTargets._item_type = AdditionalRouteTargetsItem + + class StructuredConfig(EosCliConfigGen): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "address_families": {"type": AddressFamilies, "default": lambda cls: coerce_type(["evpn"], target_type=cls)}, + "description": {"type": str}, + "vrf_vni": {"type": int}, + "vrf_id": {"type": int}, + "rd_override": {"type": str}, + "rt_override": {"type": str}, + "mlag_ibgp_peering_ipv4_pool": {"type": str}, + "ip_helpers": {"type": IpHelpers}, + "enable_mlag_ibgp_peering_vrfs": {"type": bool}, + "redistribute_mlag_ibgp_peering_vrfs": {"type": bool}, + "mlag_ibgp_peering_vlan": {"type": int}, + "vtep_diagnostic": {"type": VtepDiagnostic}, + "ospf": {"type": Ospf}, + "redistribute_ospf": {"type": bool, "default": True}, + "evpn_l3_multicast": {"type": EvpnL3Multicast}, + "pim_rp_addresses": {"type": PimRpAddresses}, + "evpn_l2_multi_domain": {"type": bool}, + "svis": {"type": Svis}, + "l3_interfaces": {"type": L3Interfaces}, + "loopbacks": {"type": Loopbacks}, + "static_routes": {"type": StaticRoutes}, + "ipv6_static_routes": {"type": Ipv6StaticRoutes}, + "redistribute_static": {"type": bool}, + "redistribute_connected": {"type": bool, "default": True}, + "bgp_peers": {"type": BgpPeers}, + "bgp": {"type": Bgp}, + "bgp_peer_groups": {"type": BgpPeerGroups}, + "additional_route_targets": {"type": AdditionalRouteTargets}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + name: str + address_families: AddressFamilies + """ + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["evpn"], target_type=cls)` + """ + description: str | None + """VRF description.""" + vrf_vni: int | None + """ + Required if "vrf_id" is not set. + The VRF VNI range is not limited, but if vrf_id is not set, + "vrf_vni" is used for calculating MLAG iBGP peering vlan id. + "vrf_vni" may also be used for VRF + RD/RT ID. See "overlay_rd_type" and "overlay_rt_type" for details. + See + "mlag_ibgp_peering_vrfs.base_vlan" for details. + If vrf_vni > 10000 make sure to adjust + "mac_vrf_vni_base" accordingly to avoid overlap. + """ + vrf_id: int | None + """ + Required if "vrf_vni" is not set. + "vrf_id" is used as default value for "vrf_vni" and + "ospf.process_id" unless those are set. + "vrf_id" may also be used for VRF RD/RT ID. See + "overlay_rd_type" and "overlay_rt_type" for details. + "vrf_id" is preferred over "vrf_vni" for MLAG + iBGP peering vlan, see "mlag_ibgp_peering_vrfs.base_vlan" for details. + """ + rd_override: str | None + """ + By default, the VRF RD will be derived from the pattern defined in `overlay_rd_type`. + The + rd_override allows us to override this value and statically define it. + + rd_override supports two + formats: + - A single number will be used in the RD assigned number subfield (second part of the + RD). + - A full RD string with colon separator which will override the full RD. + """ + rt_override: str | None + """ + By default, the VRF RT will be derived from the pattern defined in `overlay_rt_type`. + The + rt_override allows us to override this value and statically define it. + + rt_override supports two + formats: + - A single number will be used in the RT assigned number subfield (second part of the + RT). + - A full RT string with colon separator which will override the full RT. + """ + mlag_ibgp_peering_ipv4_pool: str | None + """ + IPv4_address/Mask + The subnet used for iBGP peering in the VRF. + Each MLAG pair will be assigned a + subnet based on the ID of the primary MLAG switch. + If not set, "mlag_peer_l3_ipv4_pool" or + "mlag_peer_ipv4_pool" will be used. + """ + ip_helpers: IpHelpers + """ + IP helper for DHCP relay. + + Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is + `ip_helper` (`str`). + """ + enable_mlag_ibgp_peering_vrfs: bool | None + """ + MLAG iBGP peering per VRF. + By default an iBGP peering is configured per VRF between MLAG peers on + separate VLANs. + Setting `enable_mlag_ibgp_peering_vrfs: false` under a VRF overrides the tenant-wide + setting. + """ + redistribute_mlag_ibgp_peering_vrfs: bool | None + """ + Redistribute the connected subnet for the MLAG iBGP peering per VRF into overlay BGP. + By default the + iBGP peering subnet is not redistributed into the overlay routing protocol per VRF. + Setting + `redistribute_mlag_ibgp_peering_vrfs` under a VRF overrides the tenant-wide setting. + """ + mlag_ibgp_peering_vlan: int | None + """ + Manually define the VLAN used on the MLAG pair for the iBGP session. + By default this parameter is + calculated using the following formula: `` + `` - 1. + """ + vtep_diagnostic: VtepDiagnostic + """ + Enable VTEP Network diagnostics. + This will create a loopback with virtual source-nat enable to + perform diagnostics from the switch. + + + Subclass of AvdModel. + """ + ospf: Ospf + """ + Router OSPF configuration. + This will create an OSPF routing instance in the tenant VRF. If there is + no nodes definition, the OSPF instance will be + created on all leafs where the VRF is deployed. This + will also cause automatic OSPF redistribution into BGP unless + explicitly turned off with + "redistribute_ospf: false". + + + Subclass of AvdModel. + """ + redistribute_ospf: bool + """ + Non-selectively enabling or disabling redistribute ospf inside the VRF. + + Default value: `True` + """ + evpn_l3_multicast: EvpnL3Multicast + """ + Explicitly enable or disable evpn_l3_multicast to override setting of + `.[].evpn_l3_multicast.enabled`. + Allow override of + `.[].evpn_l3_multicast` node_settings. + Requires `evpn_multicast` to also be + set to `true`. + + + Subclass of AvdModel. + """ + pim_rp_addresses: PimRpAddresses + """ + For each group of nodes, allow configuration of RP Addresses & associated groups. + + + Subclass of + AvdList with `PimRpAddressesItem` items. + """ + evpn_l2_multi_domain: bool | None + """ + Explicitly extend all VLANs/VLAN-Aware Bundles inside the VRF to remote EVPN domains. + Overrides + `[].evpn_l2_multi_domain`. + """ + svis: Svis + """ + List of SVIs. + This will create both the L3 SVI and L2 VLAN based on filters applied to the node. + Subclass of AvdList with `SvisItem` items. + """ + l3_interfaces: L3Interfaces + """ + List of L3 interfaces. + This will create IP routed interface inside VRF. Length of interfaces, nodes + and ip_addresses must match. + + + Subclass of AvdList with `L3InterfacesItem` items. + """ + loopbacks: Loopbacks + """ + List of Loopback interfaces. + This will create Loopback interfaces inside the VRF. + + + Subclass of + AvdList with `LoopbacksItem` items. + """ + static_routes: StaticRoutes + """ + List of static routes for v4 and/or v6. + This will create static routes inside the tenant VRF. + If + nodes are not specified, all l3leafs that carry the VRF will also be applied the static routes. + If a + node has a static route in the VRF, redistribute static will be automatically enabled in that VRF. + This automatic behavior can be overridden non-selectively with the redistribute_static knob for the + VRF. + + + Subclass of AvdList with `StaticRoutesItem` items. + """ + ipv6_static_routes: Ipv6StaticRoutes + """Subclass of AvdList with `Ipv6StaticRoutesItem` items.""" + redistribute_static: bool | None + """Enable or disable the redistribution of all static routes to BGP in the VRF.""" + redistribute_connected: bool + """ + Enable or disable the redistribution of all connected routes to BGP in the VRF. Note this is not + applicable to VRF `default`. + + Default value: `True` + """ + bgp_peers: BgpPeers + """ + List of BGP peer definitions. + This will configure BGP neighbors inside the tenant VRF for peering + with external devices. + The configured peer will automatically be activated for ipv4 or ipv6 address + family based on the ip address. + Note, only ipv4 and ipv6 address families are currently supported in + eos_designs. + For other address families, use custom_structured configuration with + eos_cli_config_gen. + + + Subclass of AvdList with `BgpPeersItem` items. + """ + bgp: Bgp + """Subclass of AvdModel.""" + bgp_peer_groups: BgpPeerGroups + """ + List of BGP peer groups definitions. + This will configure BGP peer groups to be used inside the + tenant VRF for peering with external devices. + Since BGP peer groups are configured at higher BGP + level, shared between VRFs, + peer_group names should not overlap between VRFs. + + + Subclass of AvdList + with `BgpPeerGroupsItem` items. + """ + additional_route_targets: AdditionalRouteTargets + """ + Configuration of extra route-targets for this VRF. Useful for route-leaking or gateway between + address families. + + Subclass of AvdList with `AdditionalRouteTargetsItem` items. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the root level of the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + address_families: AddressFamilies | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + vrf_vni: int | None | UndefinedType = Undefined, + vrf_id: int | None | UndefinedType = Undefined, + rd_override: str | None | UndefinedType = Undefined, + rt_override: str | None | UndefinedType = Undefined, + mlag_ibgp_peering_ipv4_pool: str | None | UndefinedType = Undefined, + ip_helpers: IpHelpers | UndefinedType = Undefined, + enable_mlag_ibgp_peering_vrfs: bool | None | UndefinedType = Undefined, + redistribute_mlag_ibgp_peering_vrfs: bool | None | UndefinedType = Undefined, + mlag_ibgp_peering_vlan: int | None | UndefinedType = Undefined, + vtep_diagnostic: VtepDiagnostic | UndefinedType = Undefined, + ospf: Ospf | UndefinedType = Undefined, + redistribute_ospf: bool | UndefinedType = Undefined, + evpn_l3_multicast: EvpnL3Multicast | UndefinedType = Undefined, + pim_rp_addresses: PimRpAddresses | UndefinedType = Undefined, + evpn_l2_multi_domain: bool | None | UndefinedType = Undefined, + svis: Svis | UndefinedType = Undefined, + l3_interfaces: L3Interfaces | UndefinedType = Undefined, + loopbacks: Loopbacks | UndefinedType = Undefined, + static_routes: StaticRoutes | UndefinedType = Undefined, + ipv6_static_routes: Ipv6StaticRoutes | UndefinedType = Undefined, + redistribute_static: bool | None | UndefinedType = Undefined, + redistribute_connected: bool | UndefinedType = Undefined, + bgp_peers: BgpPeers | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + bgp_peer_groups: BgpPeerGroups | UndefinedType = Undefined, + additional_route_targets: AdditionalRouteTargets | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + VrfsItem. + + + Subclass of AvdModel. + + Args: + name: name + address_families: Subclass of AvdList with `str` items. + description: VRF description. + vrf_vni: + Required if "vrf_id" is not set. + The VRF VNI range is not limited, but if vrf_id is not set, + "vrf_vni" is used for calculating MLAG iBGP peering vlan id. + "vrf_vni" may also be used for VRF + RD/RT ID. See "overlay_rd_type" and "overlay_rt_type" for details. + See + "mlag_ibgp_peering_vrfs.base_vlan" for details. + If vrf_vni > 10000 make sure to adjust + "mac_vrf_vni_base" accordingly to avoid overlap. + vrf_id: + Required if "vrf_vni" is not set. + "vrf_id" is used as default value for "vrf_vni" and + "ospf.process_id" unless those are set. + "vrf_id" may also be used for VRF RD/RT ID. See + "overlay_rd_type" and "overlay_rt_type" for details. + "vrf_id" is preferred over "vrf_vni" for MLAG + iBGP peering vlan, see "mlag_ibgp_peering_vrfs.base_vlan" for details. + rd_override: + By default, the VRF RD will be derived from the pattern defined in `overlay_rd_type`. + The + rd_override allows us to override this value and statically define it. + + rd_override supports two + formats: + - A single number will be used in the RD assigned number subfield (second part of the + RD). + - A full RD string with colon separator which will override the full RD. + rt_override: + By default, the VRF RT will be derived from the pattern defined in `overlay_rt_type`. + The + rt_override allows us to override this value and statically define it. + + rt_override supports two + formats: + - A single number will be used in the RT assigned number subfield (second part of the + RT). + - A full RT string with colon separator which will override the full RT. + mlag_ibgp_peering_ipv4_pool: + IPv4_address/Mask + The subnet used for iBGP peering in the VRF. + Each MLAG pair will be assigned a + subnet based on the ID of the primary MLAG switch. + If not set, "mlag_peer_l3_ipv4_pool" or + "mlag_peer_ipv4_pool" will be used. + ip_helpers: + IP helper for DHCP relay. + + Subclass of AvdIndexedList with `IpHelpersItem` items. Primary key is + `ip_helper` (`str`). + enable_mlag_ibgp_peering_vrfs: + MLAG iBGP peering per VRF. + By default an iBGP peering is configured per VRF between MLAG peers on + separate VLANs. + Setting `enable_mlag_ibgp_peering_vrfs: false` under a VRF overrides the tenant-wide + setting. + redistribute_mlag_ibgp_peering_vrfs: + Redistribute the connected subnet for the MLAG iBGP peering per VRF into overlay BGP. + By default the + iBGP peering subnet is not redistributed into the overlay routing protocol per VRF. + Setting + `redistribute_mlag_ibgp_peering_vrfs` under a VRF overrides the tenant-wide setting. + mlag_ibgp_peering_vlan: + Manually define the VLAN used on the MLAG pair for the iBGP session. + By default this parameter is + calculated using the following formula: `` + `` - 1. + vtep_diagnostic: + Enable VTEP Network diagnostics. + This will create a loopback with virtual source-nat enable to + perform diagnostics from the switch. + + + Subclass of AvdModel. + ospf: + Router OSPF configuration. + This will create an OSPF routing instance in the tenant VRF. If there is + no nodes definition, the OSPF instance will be + created on all leafs where the VRF is deployed. This + will also cause automatic OSPF redistribution into BGP unless + explicitly turned off with + "redistribute_ospf: false". + + + Subclass of AvdModel. + redistribute_ospf: Non-selectively enabling or disabling redistribute ospf inside the VRF. + evpn_l3_multicast: + Explicitly enable or disable evpn_l3_multicast to override setting of + `.[].evpn_l3_multicast.enabled`. + Allow override of + `.[].evpn_l3_multicast` node_settings. + Requires `evpn_multicast` to also be + set to `true`. + + + Subclass of AvdModel. + pim_rp_addresses: + For each group of nodes, allow configuration of RP Addresses & associated groups. + + + Subclass of + AvdList with `PimRpAddressesItem` items. + evpn_l2_multi_domain: + Explicitly extend all VLANs/VLAN-Aware Bundles inside the VRF to remote EVPN domains. + Overrides + `[].evpn_l2_multi_domain`. + svis: + List of SVIs. + This will create both the L3 SVI and L2 VLAN based on filters applied to the node. + Subclass of AvdList with `SvisItem` items. + l3_interfaces: + List of L3 interfaces. + This will create IP routed interface inside VRF. Length of interfaces, nodes + and ip_addresses must match. + + + Subclass of AvdList with `L3InterfacesItem` items. + loopbacks: + List of Loopback interfaces. + This will create Loopback interfaces inside the VRF. + + + Subclass of + AvdList with `LoopbacksItem` items. + static_routes: + List of static routes for v4 and/or v6. + This will create static routes inside the tenant VRF. + If + nodes are not specified, all l3leafs that carry the VRF will also be applied the static routes. + If a + node has a static route in the VRF, redistribute static will be automatically enabled in that VRF. + This automatic behavior can be overridden non-selectively with the redistribute_static knob for the + VRF. + + + Subclass of AvdList with `StaticRoutesItem` items. + ipv6_static_routes: Subclass of AvdList with `Ipv6StaticRoutesItem` items. + redistribute_static: Enable or disable the redistribution of all static routes to BGP in the VRF. + redistribute_connected: + Enable or disable the redistribution of all connected routes to BGP in the VRF. Note this is not + applicable to VRF `default`. + bgp_peers: + List of BGP peer definitions. + This will configure BGP neighbors inside the tenant VRF for peering + with external devices. + The configured peer will automatically be activated for ipv4 or ipv6 address + family based on the ip address. + Note, only ipv4 and ipv6 address families are currently supported in + eos_designs. + For other address families, use custom_structured configuration with + eos_cli_config_gen. + + + Subclass of AvdList with `BgpPeersItem` items. + bgp: Subclass of AvdModel. + bgp_peer_groups: + List of BGP peer groups definitions. + This will configure BGP peer groups to be used inside the + tenant VRF for peering with external devices. + Since BGP peer groups are configured at higher BGP + level, shared between VRFs, + peer_group names should not overlap between VRFs. + + + Subclass of AvdList + with `BgpPeerGroupsItem` items. + additional_route_targets: + Configuration of extra route-targets for this VRF. Useful for route-leaking or gateway between + address families. + + Subclass of AvdList with `AdditionalRouteTargetsItem` items. + raw_eos_cli: EOS CLI rendered directly on the root level of the final EOS configuration. + structured_config: + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Vrfs(AvdIndexedList[str, VrfsItem]): + """Subclass of AvdIndexedList with `VrfsItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Vrfs._item_type = VrfsItem + + class L2vlansItem(AvdModel): + """Subclass of AvdModel.""" + + class Tags(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tags._item_type = str + + class TrunkGroups(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + TrunkGroups._item_type = str + + class EvpnL2Multicast(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "_custom_data": {"type": dict}} + enabled: bool | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, enabled: bool | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + EvpnL2Multicast. + + + Subclass of AvdModel. + + Args: + enabled: enabled + _custom_data: _custom_data + + """ + + class IgmpSnoopingQuerier(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "source_address": {"type": str}, + "version": {"type": int}, + "fast_leave": {"type": bool}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Will be enabled automatically if evpn_l2_multicast is enabled.""" + source_address: str | None + """ + IPv4_address + If not set, IP address of "Loopback0" will be used. + """ + version: Literal[1, 2, 3] | None + """IGMP Version (By default EOS uses IGMP version 2 for IGMP querier).""" + fast_leave: bool | None + """Enable IGMP snooping fast-leave feature.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + source_address: str | None | UndefinedType = Undefined, + version: Literal[1, 2, 3] | None | UndefinedType = Undefined, + fast_leave: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IgmpSnoopingQuerier. + + + Subclass of AvdModel. + + Args: + enabled: Will be enabled automatically if evpn_l2_multicast is enabled. + source_address: + IPv4_address + If not set, IP address of "Loopback0" will be used. + version: IGMP Version (By default EOS uses IGMP version 2 for IGMP querier). + fast_leave: Enable IGMP snooping fast-leave feature. + _custom_data: _custom_data + + """ + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + class StructuredConfig(EosCliConfigGen.RouterBgp.VlansItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "structured_config": {"type": StructuredConfig}, + "raw_eos_cli": {"type": str}, + "_custom_data": {"type": dict}, + } + structured_config: StructuredConfig + """ + Custom structured config added under router_bgp.vlans.[id=] for eos_cli_config_gen. + This + configuration will not be applied to vlan aware bundles. + + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """ + EOS cli commands rendered on router_bgp.vlans. + This configuration will not be applied to vlan aware + bundles. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + structured_config: StructuredConfig | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + structured_config: + Custom structured config added under router_bgp.vlans.[id=] for eos_cli_config_gen. + This + configuration will not be applied to vlan aware bundles. + + + Subclass of AvdModel. + raw_eos_cli: + EOS cli commands rendered on router_bgp.vlans. + This configuration will not be applied to vlan aware + bundles. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "vni_override": {"type": int}, + "rt_override": {"type": str}, + "rd_override": {"type": str}, + "name": {"type": str}, + "tags": {"type": Tags, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "vxlan": {"type": bool, "default": True}, + "spanning_tree_priority": {"type": int}, + "evpn_vlan_bundle": {"type": str}, + "trunk_groups": {"type": TrunkGroups}, + "evpn_l2_multi_domain": {"type": bool}, + "evpn_l2_multicast": {"type": EvpnL2Multicast}, + "igmp_snooping_enabled": {"type": bool}, + "igmp_snooping_querier": {"type": IgmpSnoopingQuerier}, + "bgp": {"type": Bgp}, + "_custom_data": {"type": dict}, + } + id: int + """VLAN ID.""" + vni_override: int | None + """ + By default the VNI will be derived from mac_vrf_vni_base. + The vni_override, allows to override this + value and statically define it. + """ + rt_override: str | None + """ + By default the MAC VRF RT will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rt_override will default to vni_override if set. + rt_override supports two formats: + - A single number which will be used in the RT fields instead of + mac_vrf_id/mac_vrf_vni (see 'overlay_rt_type' for details). + - A full RT string with colon + separator which will override the full RT. + """ + rd_override: str | None + """ + By default the MAC VRF RD will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rd_override will default to rt_override or + vni_override if set. + + rd_override supports two formats: + - A single number which will be used in + the RD assigned number field instead of mac_vrf_id/mac_vrf_vni (see 'overlay_rd_type' for details). + - A full RD string with colon separator which will override the full RD. + """ + name: str + """VLAN name.""" + tags: Tags + """ + Tags leveraged for networks services filtering. + Tags are matched against filter.tags defined under + node type settings. + Tags are also matched against the node_group name under node type settings. + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + vxlan: bool + """ + Extend this L2VLAN over VXLAN. + + Default value: `True` + """ + spanning_tree_priority: int | None + """ + Setting spanning-tree priority per VLAN is only supported with `spanning_tree_mode: rapid-pvst` + under node type settings. + The default priority for rapid-PVST is set under the node type settings + with `spanning_tree_priority` (default=32768). + """ + evpn_vlan_bundle: str | None + """ + Name of a bundle defined under 'evpn_vlan_bundles' to inherit configuration. + This setting overrides + "evpn_vlan_bundle" set at tenant level. + The common option "evpn_vlan_aware_bundles" is disregarded + for this option. + """ + trunk_groups: TrunkGroups + """Subclass of AvdList with `str` items.""" + evpn_l2_multi_domain: bool | None + """ + Explicitly extend this VLAN to remote EVPN domains. + Overrides + `[].evpn_l2_multi_domain`. + """ + evpn_l2_multicast: EvpnL2Multicast + """ + Explicitly enable or disable evpn_l2_multicast to override setting of + `.[].evpn_l2_multicast.enabled`. + When evpn_l2_multicast.enabled is set to true + for a vlan or a tenant, igmp snooping and igmp snooping querier will always be enabled, overriding + those individual settings. + Requires `evpn_multicast` to also be set to `true`. + + + Subclass of + AvdModel. + """ + igmp_snooping_enabled: bool | None + """Enable or disable IGMP snooping (Enabled by default on EOS).""" + igmp_snooping_querier: IgmpSnoopingQuerier + """ + Enable igmp snooping querier, by default using IP address of Loopback 0. + When enabled, igmp snooping + querier will only be configured on l3 devices, i.e., uplink_type: p2p. + + + Subclass of AvdModel. + """ + bgp: Bgp + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + vni_override: int | None | UndefinedType = Undefined, + rt_override: str | None | UndefinedType = Undefined, + rd_override: str | None | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + tags: Tags | UndefinedType = Undefined, + vxlan: bool | UndefinedType = Undefined, + spanning_tree_priority: int | None | UndefinedType = Undefined, + evpn_vlan_bundle: str | None | UndefinedType = Undefined, + trunk_groups: TrunkGroups | UndefinedType = Undefined, + evpn_l2_multi_domain: bool | None | UndefinedType = Undefined, + evpn_l2_multicast: EvpnL2Multicast | UndefinedType = Undefined, + igmp_snooping_enabled: bool | None | UndefinedType = Undefined, + igmp_snooping_querier: IgmpSnoopingQuerier | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L2vlansItem. + + + Subclass of AvdModel. + + Args: + id: VLAN ID. + vni_override: + By default the VNI will be derived from mac_vrf_vni_base. + The vni_override, allows to override this + value and statically define it. + rt_override: + By default the MAC VRF RT will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rt_override will default to vni_override if set. + rt_override supports two formats: + - A single number which will be used in the RT fields instead of + mac_vrf_id/mac_vrf_vni (see 'overlay_rt_type' for details). + - A full RT string with colon + separator which will override the full RT. + rd_override: + By default the MAC VRF RD will be derived from mac_vrf_id_base + vlan_id. + The rt_override allows us + to override this value and statically define it. + rd_override will default to rt_override or + vni_override if set. + + rd_override supports two formats: + - A single number which will be used in + the RD assigned number field instead of mac_vrf_id/mac_vrf_vni (see 'overlay_rd_type' for details). + - A full RD string with colon separator which will override the full RD. + name: VLAN name. + tags: + Tags leveraged for networks services filtering. + Tags are matched against filter.tags defined under + node type settings. + Tags are also matched against the node_group name under node type settings. + Subclass of AvdList with `str` items. + vxlan: Extend this L2VLAN over VXLAN. + spanning_tree_priority: + Setting spanning-tree priority per VLAN is only supported with `spanning_tree_mode: rapid-pvst` + under node type settings. + The default priority for rapid-PVST is set under the node type settings + with `spanning_tree_priority` (default=32768). + evpn_vlan_bundle: + Name of a bundle defined under 'evpn_vlan_bundles' to inherit configuration. + This setting overrides + "evpn_vlan_bundle" set at tenant level. + The common option "evpn_vlan_aware_bundles" is disregarded + for this option. + trunk_groups: Subclass of AvdList with `str` items. + evpn_l2_multi_domain: + Explicitly extend this VLAN to remote EVPN domains. + Overrides + `[].evpn_l2_multi_domain`. + evpn_l2_multicast: + Explicitly enable or disable evpn_l2_multicast to override setting of + `.[].evpn_l2_multicast.enabled`. + When evpn_l2_multicast.enabled is set to true + for a vlan or a tenant, igmp snooping and igmp snooping querier will always be enabled, overriding + those individual settings. + Requires `evpn_multicast` to also be set to `true`. + + + Subclass of + AvdModel. + igmp_snooping_enabled: Enable or disable IGMP snooping (Enabled by default on EOS). + igmp_snooping_querier: + Enable igmp snooping querier, by default using IP address of Loopback 0. + When enabled, igmp snooping + querier will only be configured on l3 devices, i.e., uplink_type: p2p. + + + Subclass of AvdModel. + bgp: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L2vlans(AvdList[L2vlansItem]): + """Subclass of AvdList with `L2vlansItem` items.""" + + L2vlans._item_type = L2vlansItem + + class PointToPointServicesItem(AvdModel): + """Subclass of AvdModel.""" + + class SubinterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"number": {"type": int}, "_custom_data": {"type": dict}} + number: int + """Subinterface number.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, number: int | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + SubinterfacesItem. + + + Subclass of AvdModel. + + Args: + number: Subinterface number. + _custom_data: _custom_data + + """ + + class Subinterfaces(AvdIndexedList[int, SubinterfacesItem]): + """Subclass of AvdIndexedList with `SubinterfacesItem` items. Primary key is `number` (`int`).""" + + _primary_key: ClassVar[str] = "number" + + Subinterfaces._item_type = SubinterfacesItem + + class EndpointsItem(AvdModel): + """Subclass of AvdModel.""" + + class Nodes(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Nodes._item_type = str + + class Interfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Interfaces._item_type = str + + class PortChannel(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"mode": {"type": str}, "short_esi": {"type": str}, "_custom_data": {"type": dict}} + mode: Literal["active", "on"] | None + short_esi: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + mode: Literal["active", "on"] | None | UndefinedType = Undefined, + short_esi: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PortChannel. + + + Subclass of AvdModel. + + Args: + mode: mode + short_esi: short_esi + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "nodes": {"type": Nodes}, + "interfaces": {"type": Interfaces}, + "port_channel": {"type": PortChannel}, + "_custom_data": {"type": dict}, + } + id: int + """Pseudowire ID on this endpoint.""" + nodes: Nodes + """ + Usually one node. With ESI multihoming we support two nodes per pseudowire endpoint. + + Subclass of + AvdList with `str` items. + """ + interfaces: Interfaces + """ + Interfaces patched to the pseudowire on this endpoints. + The list of interfaces is mapped to the list + of nodes, so they must have the same length. + + + Subclass of AvdList with `str` items. + """ + port_channel: PortChannel + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + interfaces: Interfaces | UndefinedType = Undefined, + port_channel: PortChannel | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EndpointsItem. + + + Subclass of AvdModel. + + Args: + id: Pseudowire ID on this endpoint. + nodes: + Usually one node. With ESI multihoming we support two nodes per pseudowire endpoint. + + Subclass of + AvdList with `str` items. + interfaces: + Interfaces patched to the pseudowire on this endpoints. + The list of interfaces is mapped to the list + of nodes, so they must have the same length. + + + Subclass of AvdList with `str` items. + port_channel: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class Endpoints(AvdList[EndpointsItem]): + """Subclass of AvdList with `EndpointsItem` items.""" + + Endpoints._item_type = EndpointsItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "type": {"type": str, "default": "vpws-pseudowire"}, + "subinterfaces": {"type": Subinterfaces}, + "endpoints": {"type": Endpoints}, + "lldp_disable": {"type": bool}, + "_custom_data": {"type": dict}, + } + name: str + """Pseudowire name.""" + type: Literal["vpws-pseudowire"] + """Default value: `"vpws-pseudowire"`""" + subinterfaces: Subinterfaces + """ + Subinterfaces will create subinterfaces and additional pseudowires/patch panel config for each + endpoint. + + Subclass of AvdIndexedList with `SubinterfacesItem` items. Primary key is `number` + (`int`). + """ + endpoints: Endpoints + """ + Pseudowire terminating endpoints. Must have exactly two items. + + Subclass of AvdList with + `EndpointsItem` items. + """ + lldp_disable: bool | None + """Disable LLDP RX/TX on port mode pseudowire services.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + type: Literal["vpws-pseudowire"] | UndefinedType = Undefined, + subinterfaces: Subinterfaces | UndefinedType = Undefined, + endpoints: Endpoints | UndefinedType = Undefined, + lldp_disable: bool | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PointToPointServicesItem. + + + Subclass of AvdModel. + + Args: + name: Pseudowire name. + type: type + subinterfaces: + Subinterfaces will create subinterfaces and additional pseudowires/patch panel config for each + endpoint. + + Subclass of AvdIndexedList with `SubinterfacesItem` items. Primary key is `number` + (`int`). + endpoints: + Pseudowire terminating endpoints. Must have exactly two items. + + Subclass of AvdList with + `EndpointsItem` items. + lldp_disable: Disable LLDP RX/TX on port mode pseudowire services. + _custom_data: _custom_data + + """ + + class PointToPointServices(AvdIndexedList[str, PointToPointServicesItem]): + """Subclass of AvdIndexedList with `PointToPointServicesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + PointToPointServices._item_type = PointToPointServicesItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "mac_vrf_vni_base": {"type": int}, + "mac_vrf_id_base": {"type": int}, + "vlan_aware_bundle_number_base": {"type": int, "default": 0}, + "pseudowire_rt_base": {"type": int}, + "enable_mlag_ibgp_peering_vrfs": {"type": bool, "default": True}, + "redistribute_mlag_ibgp_peering_vrfs": {"type": bool, "default": False}, + "evpn_vlan_bundle": {"type": str}, + "bgp_peer_groups": {"type": BgpPeerGroups}, + "evpn_l2_multicast": {"type": EvpnL2Multicast}, + "evpn_l3_multicast": {"type": EvpnL3Multicast}, + "pim_rp_addresses": {"type": PimRpAddresses}, + "igmp_snooping_querier": {"type": IgmpSnoopingQuerier}, + "evpn_l2_multi_domain": {"type": bool, "default": True}, + "vrfs": {"type": Vrfs}, + "l2vlans": {"type": L2vlans}, + "point_to_point_services": {"type": PointToPointServices}, + "_custom_data": {"type": dict}, + } + name: str + """ + Specify a tenant name. + Tenant provide a construct to group L3 VRFs and L2 VLANs. + Networks services + can be filtered by tenant name. + """ + mac_vrf_vni_base: int | None + """ + Base number for MAC VRF VXLAN Network Identifier (required with VXLAN). + VXLAN VNI is derived from + the base number with simple addition. + i.e. mac_vrf_vni_base = 10000, svi 100 = VNI 10100, svi 300 = + VNI 10300. + """ + mac_vrf_id_base: int | None + """ + If not set, "mac_vrf_vni_base" will be used. + Base number for MAC VRF RD/RT ID (Required unless + mac_vrf_vni_base is set) + ID is derived from the base number with simple addition. + i.e. + mac_vrf_id_base = 10000, svi 100 = RD/RT 10100, svi 300 = RD/RT 10300. + """ + vlan_aware_bundle_number_base: int + """ + Base number for VLAN aware bundle RD/RT. + The "Assigned Number" part of RD/RT is derived from vrf_vni + + vlan_aware_bundle_number_base. + + Default value: `0` + """ + pseudowire_rt_base: int | None + """ + Pseudowire RT base, used to generate route targets for VPWS services. + Avoid overlapping route target + spaces between different services. + """ + enable_mlag_ibgp_peering_vrfs: bool + """ + MLAG iBGP peering per VRF. + By default an iBGP peering is configured per VRF between MLAG peers on + separate VLANs. + Setting `enable_mlag_ibgp_peering_vrfs` false under a tenant will change this + default to prevent configuration of these peerings and VLANs for all VRFs in the tenant. + This + setting can be overridden per VRF. + + Default value: `True` + """ + redistribute_mlag_ibgp_peering_vrfs: bool + """ + Redistribute the connected subnet for the MLAG iBGP peering per VRF into overlay BGP. + By default the + iBGP peering subnet is not redistributed into the overlay routing protocol per VRF. + Setting + `redistribute_mlag_ibgp_peering_vrfs: true` under a tenant will change this default to + redistribution of these subnets for all VRFs in the tenant. + This setting can be overridden per VRF. + + Default value: `False` + """ + evpn_vlan_bundle: str | None + """ + Enable `evpn_vlan_bundle` for all l2vlans and SVIs under the tenant. This `evpn_vlan_bundle` should + be present in `evpn_vlan_bundles`. + """ + bgp_peer_groups: BgpPeerGroups + """ + List of BGP peer groups definitions. + This will configure BGP peer groups to be used inside the + tenant VRF for peering with external devices. + Since BGP peer groups are configured at higher BGP + level, shared between VRFs, + peer_group names should not overlap between VRFs. + + + Subclass of + AvdIndexedList with `BgpPeerGroupsItem` items. Primary key is `name` (`str`). + """ + evpn_l2_multicast: EvpnL2Multicast + """ + Enable EVPN L2 Multicast for all SVIs and l2vlans within Tenant. + - Multicast group binding is + created only for Multicast traffic. BULL traffic will use ingress-replication. + - Configures binding + between VXLAN, VLAN, and multicast group IPv4 address using the following formula: + < + evpn_l2_multicast.underlay_l2_multicast_group_ipv4_pool > + < vlan_id - 1 > + < + evpn_l2_multicast.underlay_l2_multicast_group_ipv4_pool_offset >. + - The recommendation is to assign + a /20 block within the 232.0.0.0/8 Source-Specific Multicast range. + - Enables `redistribute igmp` on + the router bgp MAC VRF. + - When evpn_l2_multicast.enabled is true for a VLAN or a tenant, "igmp + snooping" and "igmp snooping querier" will always be enabled - overriding those individual settings. + - Requires `evpn_multicast` to also be set to `true`. + + + Subclass of AvdModel. + """ + evpn_l3_multicast: EvpnL3Multicast + """ + Enable L3 Multicast for all SVIs and l3vlans within Tenant. + - In the evpn-l3ls design type, this + enables L3 EVPN Multicast (aka OISM)'. + - Multicast group binding for VRF is created only for + Multicast traffic. BULL traffic will use ingress-replication. + - Configures binding between VXLAN, + VLAN, and multicast group IPv4 address using the following formula: + < + l3_multicast.evpn_underlay_l3_multicast_group_ipv4_pool > + < vrf_id - 1 > + < + l3_multicast.evpn_underlay_l3_multicast_group_ipv4_pool_offset >. + - The recommendation is to assign + a /20 block within the 232.0.0.0/8 Source-Specific Multicast range. + - If enabled on an SVI using the + anycast default gateway feature, a diagnostic loopback (see below) MUST be configured to source IGMP + traffic. + - Enables `evpn multicast` on the router bgp VRF. + - When enabled on an SVI: + - If + switch is part of an MLAG pair, enables "pim ipv4 sparse-mode" on the SVI. + - If switch is + standalone or A-A MH, enables "ip igmp" on the SVI. + - If "ip address virtual" is configured, + enables "pim ipv4 local-interface" and uses the diagnostic Loopback defined in the VRF + - Requires + `evpn_multicast` to also be set to `true`. + + + Subclass of AvdModel. + """ + pim_rp_addresses: PimRpAddresses + """ + For each group of nodes, allow configuration of RP Addresses & associated groups. + + + Subclass of + AvdList with `PimRpAddressesItem` items. + """ + igmp_snooping_querier: IgmpSnoopingQuerier + """ + Enable IGMP snooping querier for each SVI/l2vlan within tenant, by default using IP address of + Loopback 0. + When enabled, IGMP snooping querier will only be configured on L3 devices, i.e., + uplink_type: p2p. + + + Subclass of AvdModel. + """ + evpn_l2_multi_domain: bool + """ + Explicitly extend all VLANs/VLAN-Aware Bundles inside the tenant to remote EVPN domains. + + Default value: `True` + """ + vrfs: Vrfs + """ + VRFs will only be configured on a node if any of the underlying objects like `svis` or + `l3_interfaces` apply to the node. + + It is recommended to only define a VRF in one Tenant. If the + same VRF name is used across multiple tenants and those tenants + are accepted by `filter.tenants` on + the node, any object set under the duplicate VRFs must either be unique or be an exact match. + + VRF + "default" is partially supported under network-services. Currently the supported options for + "default" vrf are route-target, + route-distinguisher settings, structured_config, raw_eos_cli in bgp + and SVIs are the only supported interface type. + Vlan-aware-bundles are supported as well inside + default vrf. OSPF is not supported currently. + + + Subclass of AvdIndexedList with `VrfsItem` items. + Primary key is `name` (`str`). + """ + l2vlans: L2vlans + """ + Define L2 network services organized by vlan id. + + Subclass of AvdList with `L2vlansItem` items. + """ + point_to_point_services: PointToPointServices + """ + Point to point services (pseudowires). + Only supported for node types with "network_services.l1: + true". + By default this is only set for node type "pe" with "design.type: mpls" + + + Subclass of + AvdIndexedList with `PointToPointServicesItem` items. Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + mac_vrf_vni_base: int | None | UndefinedType = Undefined, + mac_vrf_id_base: int | None | UndefinedType = Undefined, + vlan_aware_bundle_number_base: int | UndefinedType = Undefined, + pseudowire_rt_base: int | None | UndefinedType = Undefined, + enable_mlag_ibgp_peering_vrfs: bool | UndefinedType = Undefined, + redistribute_mlag_ibgp_peering_vrfs: bool | UndefinedType = Undefined, + evpn_vlan_bundle: str | None | UndefinedType = Undefined, + bgp_peer_groups: BgpPeerGroups | UndefinedType = Undefined, + evpn_l2_multicast: EvpnL2Multicast | UndefinedType = Undefined, + evpn_l3_multicast: EvpnL3Multicast | UndefinedType = Undefined, + pim_rp_addresses: PimRpAddresses | UndefinedType = Undefined, + igmp_snooping_querier: IgmpSnoopingQuerier | UndefinedType = Undefined, + evpn_l2_multi_domain: bool | UndefinedType = Undefined, + vrfs: Vrfs | UndefinedType = Undefined, + l2vlans: L2vlans | UndefinedType = Undefined, + point_to_point_services: PointToPointServices | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NetworkServicesItem. + + + Subclass of AvdModel. + + Args: + name: + Specify a tenant name. + Tenant provide a construct to group L3 VRFs and L2 VLANs. + Networks services + can be filtered by tenant name. + mac_vrf_vni_base: + Base number for MAC VRF VXLAN Network Identifier (required with VXLAN). + VXLAN VNI is derived from + the base number with simple addition. + i.e. mac_vrf_vni_base = 10000, svi 100 = VNI 10100, svi 300 = + VNI 10300. + mac_vrf_id_base: + If not set, "mac_vrf_vni_base" will be used. + Base number for MAC VRF RD/RT ID (Required unless + mac_vrf_vni_base is set) + ID is derived from the base number with simple addition. + i.e. + mac_vrf_id_base = 10000, svi 100 = RD/RT 10100, svi 300 = RD/RT 10300. + vlan_aware_bundle_number_base: + Base number for VLAN aware bundle RD/RT. + The "Assigned Number" part of RD/RT is derived from vrf_vni + + vlan_aware_bundle_number_base. + pseudowire_rt_base: + Pseudowire RT base, used to generate route targets for VPWS services. + Avoid overlapping route target + spaces between different services. + enable_mlag_ibgp_peering_vrfs: + MLAG iBGP peering per VRF. + By default an iBGP peering is configured per VRF between MLAG peers on + separate VLANs. + Setting `enable_mlag_ibgp_peering_vrfs` false under a tenant will change this + default to prevent configuration of these peerings and VLANs for all VRFs in the tenant. + This + setting can be overridden per VRF. + redistribute_mlag_ibgp_peering_vrfs: + Redistribute the connected subnet for the MLAG iBGP peering per VRF into overlay BGP. + By default the + iBGP peering subnet is not redistributed into the overlay routing protocol per VRF. + Setting + `redistribute_mlag_ibgp_peering_vrfs: true` under a tenant will change this default to + redistribution of these subnets for all VRFs in the tenant. + This setting can be overridden per VRF. + evpn_vlan_bundle: + Enable `evpn_vlan_bundle` for all l2vlans and SVIs under the tenant. This `evpn_vlan_bundle` should + be present in `evpn_vlan_bundles`. + bgp_peer_groups: + List of BGP peer groups definitions. + This will configure BGP peer groups to be used inside the + tenant VRF for peering with external devices. + Since BGP peer groups are configured at higher BGP + level, shared between VRFs, + peer_group names should not overlap between VRFs. + + + Subclass of + AvdIndexedList with `BgpPeerGroupsItem` items. Primary key is `name` (`str`). + evpn_l2_multicast: + Enable EVPN L2 Multicast for all SVIs and l2vlans within Tenant. + - Multicast group binding is + created only for Multicast traffic. BULL traffic will use ingress-replication. + - Configures binding + between VXLAN, VLAN, and multicast group IPv4 address using the following formula: + < + evpn_l2_multicast.underlay_l2_multicast_group_ipv4_pool > + < vlan_id - 1 > + < + evpn_l2_multicast.underlay_l2_multicast_group_ipv4_pool_offset >. + - The recommendation is to assign + a /20 block within the 232.0.0.0/8 Source-Specific Multicast range. + - Enables `redistribute igmp` on + the router bgp MAC VRF. + - When evpn_l2_multicast.enabled is true for a VLAN or a tenant, "igmp + snooping" and "igmp snooping querier" will always be enabled - overriding those individual settings. + - Requires `evpn_multicast` to also be set to `true`. + + + Subclass of AvdModel. + evpn_l3_multicast: + Enable L3 Multicast for all SVIs and l3vlans within Tenant. + - In the evpn-l3ls design type, this + enables L3 EVPN Multicast (aka OISM)'. + - Multicast group binding for VRF is created only for + Multicast traffic. BULL traffic will use ingress-replication. + - Configures binding between VXLAN, + VLAN, and multicast group IPv4 address using the following formula: + < + l3_multicast.evpn_underlay_l3_multicast_group_ipv4_pool > + < vrf_id - 1 > + < + l3_multicast.evpn_underlay_l3_multicast_group_ipv4_pool_offset >. + - The recommendation is to assign + a /20 block within the 232.0.0.0/8 Source-Specific Multicast range. + - If enabled on an SVI using the + anycast default gateway feature, a diagnostic loopback (see below) MUST be configured to source IGMP + traffic. + - Enables `evpn multicast` on the router bgp VRF. + - When enabled on an SVI: + - If + switch is part of an MLAG pair, enables "pim ipv4 sparse-mode" on the SVI. + - If switch is + standalone or A-A MH, enables "ip igmp" on the SVI. + - If "ip address virtual" is configured, + enables "pim ipv4 local-interface" and uses the diagnostic Loopback defined in the VRF + - Requires + `evpn_multicast` to also be set to `true`. + + + Subclass of AvdModel. + pim_rp_addresses: + For each group of nodes, allow configuration of RP Addresses & associated groups. + + + Subclass of + AvdList with `PimRpAddressesItem` items. + igmp_snooping_querier: + Enable IGMP snooping querier for each SVI/l2vlan within tenant, by default using IP address of + Loopback 0. + When enabled, IGMP snooping querier will only be configured on L3 devices, i.e., + uplink_type: p2p. + + + Subclass of AvdModel. + evpn_l2_multi_domain: Explicitly extend all VLANs/VLAN-Aware Bundles inside the tenant to remote EVPN domains. + vrfs: + VRFs will only be configured on a node if any of the underlying objects like `svis` or + `l3_interfaces` apply to the node. + + It is recommended to only define a VRF in one Tenant. If the + same VRF name is used across multiple tenants and those tenants + are accepted by `filter.tenants` on + the node, any object set under the duplicate VRFs must either be unique or be an exact match. + + VRF + "default" is partially supported under network-services. Currently the supported options for + "default" vrf are route-target, + route-distinguisher settings, structured_config, raw_eos_cli in bgp + and SVIs are the only supported interface type. + Vlan-aware-bundles are supported as well inside + default vrf. OSPF is not supported currently. + + + Subclass of AvdIndexedList with `VrfsItem` items. + Primary key is `name` (`str`). + l2vlans: + Define L2 network services organized by vlan id. + + Subclass of AvdList with `L2vlansItem` items. + point_to_point_services: + Point to point services (pseudowires). + Only supported for node types with "network_services.l1: + true". + By default this is only set for node type "pe" with "design.type: mpls" + + + Subclass of + AvdIndexedList with `PointToPointServicesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class NetworkServices(AvdIndexedList[str, NetworkServicesItem]): + """Subclass of AvdIndexedList with `NetworkServicesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + NetworkServices._item_type = NetworkServicesItem + + _fields: ClassVar[dict] = {"key": {"type": str}, "value": {"type": NetworkServices}} + _field_to_key_map: ClassVar[dict] = {"value": "network_services_keys_name"} + _key_to_field_map: ClassVar[dict] = {"network_services_keys_name": "value"} + key: str + """Key used as dynamic key""" + value: NetworkServices + """Value of dynamic key""" + + if TYPE_CHECKING: + + def __init__(self, *, key: str | UndefinedType = Undefined, value: NetworkServices | UndefinedType = Undefined) -> None: + """ + DynamicNetworkServicesItem. + + + Args: + key: Key used as dynamic key + value: Value of dynamic key + + """ + + class DynamicNetworkServices(AvdIndexedList[str, DynamicNetworkServicesItem]): + _primary_key: ClassVar[str] = "key" + + DynamicNetworkServices._item_type = DynamicNetworkServicesItem + + class DynamicNodeTypesItem(AvdModel): + class NodeTypes(AvdModel): + """Subclass of AvdModel.""" + + class Defaults(AvdModel): + """Subclass of AvdModel.""" + + class LinkTracking(AvdModel): + """Subclass of AvdModel.""" + + class GroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "recovery_delay": {"type": int}, + "links_minimum": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str | None + """Tracking group name.""" + recovery_delay: int | None + """default -> platform_settings_mlag_reload_delay -> 300.""" + links_minimum: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + recovery_delay: int | None | UndefinedType = Undefined, + links_minimum: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GroupsItem. + + + Subclass of AvdModel. + + Args: + name: Tracking group name. + recovery_delay: default -> platform_settings_mlag_reload_delay -> 300. + links_minimum: links_minimum + _custom_data: _custom_data + + """ + + class Groups(AvdList[GroupsItem]): + """Subclass of AvdList with `GroupsItem` items.""" + + Groups._item_type = GroupsItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "groups": {"type": Groups, "default": lambda cls: coerce_type([{"name": "LT_GROUP1"}], target_type=cls)}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + groups: Groups + """ + Link Tracking Groups. + By default a single group named "LT_GROUP1" is defined with default values. + Any groups defined under "groups" will replace the default. + + + Subclass of AvdList with `GroupsItem` + items. + + Default value: `lambda cls: coerce_type([{"name": "LT_GROUP1"}], target_type=cls)` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + groups: + Link Tracking Groups. + By default a single group named "LT_GROUP1" is defined with default values. + Any groups defined under "groups" will replace the default. + + + Subclass of AvdList with `GroupsItem` + items. + _custom_data: _custom_data + + """ + + class LacpPortIdRange(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "size": {"type": int, "default": 128}, + "offset": {"type": int, "default": 0}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + size: int + """ + Recommended size > = number of ports in the switch. + + Default value: `128` + """ + offset: int + """ + Offset is used to avoid overlapping port-id ranges of different switches. + Useful when a "connected- + endpoint" is connected to switches in different "node_groups". + + Default value: `0` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + size: int | UndefinedType = Undefined, + offset: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LacpPortIdRange. + + + Subclass of AvdModel. + + Args: + enabled: enabled + size: Recommended size > = number of ports in the switch. + offset: + Offset is used to avoid overlapping port-id ranges of different switches. + Useful when a "connected- + endpoint" is connected to switches in different "node_groups". + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen): + """Subclass of AvdModel.""" + + class UplinkInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkInterfaces._item_type = str + + class UplinkSwitchInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkSwitchInterfaces._item_type = str + + class UplinkSwitches(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkSwitches._item_type = str + + class UplinkPtp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enable": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enable: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, enable: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + UplinkPtp. + + + Subclass of AvdModel. + + Args: + enable: enable + _custom_data: _custom_data + + """ + + class UplinkMacsec(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "_custom_data": {"type": dict}} + profile: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, profile: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + UplinkMacsec. + + + Subclass of AvdModel. + + Args: + profile: profile + _custom_data: _custom_data + + """ + + class MlagPortChannelStructuredConfig(EosCliConfigGen.PortChannelInterfacesItem): + """Subclass of AvdModel.""" + + class MlagPeerVlanStructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + class MlagPeerL3VlanStructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + class BgpDefaults(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + BgpDefaults._item_type = str + + class EvpnRouteServers(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + EvpnRouteServers._item_type = str + + class Filter(AvdModel): + """Subclass of AvdModel.""" + + class Tenants(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tenants._item_type = str + + class Tags(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tags._item_type = str + + class AllowVrfs(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AllowVrfs._item_type = str + + class DenyVrfs(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DenyVrfs._item_type = str + + class AlwaysIncludeVrfsInTenants(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AlwaysIncludeVrfsInTenants._item_type = str + + _fields: ClassVar[dict] = { + "tenants": {"type": Tenants, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "tags": {"type": Tags, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "allow_vrfs": {"type": AllowVrfs, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "deny_vrfs": {"type": DenyVrfs, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "always_include_vrfs_in_tenants": {"type": AlwaysIncludeVrfsInTenants}, + "only_vlans_in_use": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + tenants: Tenants + """ + Limit configured Network Services to those defined under these Tenants. Set to ['all'] for all + Tenants (default). + This list also limits Tenants included by `always_include_vrfs_in_tenants`. + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + tags: Tags + """ + Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default). + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + allow_vrfs: AllowVrfs + """ + Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs + (default). + This list also limits VRFs included by `always_include_vrfs_in_tenants`. + + Subclass of + AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + deny_vrfs: DenyVrfs + """ + Prevent configuration of Network Services defined under these VRFs. + This list prevents the given + VRFs to be included by any other filtering mechanism. + + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + always_include_vrfs_in_tenants: AlwaysIncludeVrfsInTenants + """ + List of tenants where VRFs will be configured even if VLANs are not included in tags. + Useful for L3 + "border" leaf. + + + Subclass of AvdList with `str` items. + """ + only_vlans_in_use: bool + """ + Only configure VLANs, SVIs, VRFs in use by connected endpoints or downstream L2 switches. + Note! This + feature only considers configuration managed by eos_designs. + This excludes structured_config, + custom_structured_configuration_, raw_eos_cli, eos_cli, custom templates, configlets etc. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + tenants: Tenants | UndefinedType = Undefined, + tags: Tags | UndefinedType = Undefined, + allow_vrfs: AllowVrfs | UndefinedType = Undefined, + deny_vrfs: DenyVrfs | UndefinedType = Undefined, + always_include_vrfs_in_tenants: AlwaysIncludeVrfsInTenants | UndefinedType = Undefined, + only_vlans_in_use: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Filter. + + + Subclass of AvdModel. + + Args: + tenants: + Limit configured Network Services to those defined under these Tenants. Set to ['all'] for all + Tenants (default). + This list also limits Tenants included by `always_include_vrfs_in_tenants`. + Subclass of AvdList with `str` items. + tags: + Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default). + Subclass of AvdList with `str` items. + allow_vrfs: + Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs + (default). + This list also limits VRFs included by `always_include_vrfs_in_tenants`. + + Subclass of + AvdList with `str` items. + deny_vrfs: + Prevent configuration of Network Services defined under these VRFs. + This list prevents the given + VRFs to be included by any other filtering mechanism. + + Subclass of AvdList with `str` items. + always_include_vrfs_in_tenants: + List of tenants where VRFs will be configured even if VLANs are not included in tags. + Useful for L3 + "border" leaf. + + + Subclass of AvdList with `str` items. + only_vlans_in_use: + Only configure VLANs, SVIs, VRFs in use by connected endpoints or downstream L2 switches. + Note! This + feature only considers configuration managed by eos_designs. + This excludes structured_config, + custom_structured_configuration_, raw_eos_cli, eos_cli, custom templates, configlets etc. + _custom_data: _custom_data + + """ + + class EvpnGateway(AvdModel): + """Subclass of AvdModel.""" + + class RemotePeersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hostname": {"type": str}, + "ip_address": {"type": str}, + "bgp_as": {"type": str}, + "_custom_data": {"type": dict}, + } + hostname: str + """Hostname of remote EVPN GW server.""" + ip_address: str | None + """Peering IP of remote Route Server.""" + bgp_as: str | None + """ + Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being + interpreted as a float number. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: str | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + bgp_as: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemotePeersItem. + + + Subclass of AvdModel. + + Args: + hostname: Hostname of remote EVPN GW server. + ip_address: Peering IP of remote Route Server. + bgp_as: + Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being + interpreted as a float number. + _custom_data: _custom_data + + """ + + class RemotePeers(AvdIndexedList[str, RemotePeersItem]): + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + + _primary_key: ClassVar[str] = "hostname" + + RemotePeers._item_type = RemotePeersItem + + class EvpnL2(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enabled: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, enabled: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + EvpnL2. + + + Subclass of AvdModel. + + Args: + enabled: enabled + _custom_data: _custom_data + + """ + + class EvpnL3(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "inter_domain": {"type": bool, "default": True}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + inter_domain: bool + """Default value: `True`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + inter_domain: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnL3. + + + Subclass of AvdModel. + + Args: + enabled: enabled + inter_domain: inter_domain + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "remote_peers": {"type": RemotePeers}, + "evpn_l2": {"type": EvpnL2}, + "evpn_l3": {"type": EvpnL3}, + "_custom_data": {"type": dict}, + } + remote_peers: RemotePeers + """ + Define remote peers of the EVPN VXLAN Gateway. + If the hostname can be found in the inventory, + ip_address and BGP ASN will be automatically populated. Manual override takes precedence. + If the + peer's hostname can not be found in the inventory, ip_address and bgp_as must be defined. + + + Subclass + of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + """ + evpn_l2: EvpnL2 + """ + Enable EVPN Gateway functionality for route-types 2 (MAC-IP) and 3 (IMET). + + Subclass of AvdModel. + """ + evpn_l3: EvpnL3 + """ + Enable EVPN Gateway functionality for route-type 5 (IP-PREFIX). + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + remote_peers: RemotePeers | UndefinedType = Undefined, + evpn_l2: EvpnL2 | UndefinedType = Undefined, + evpn_l3: EvpnL3 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnGateway. + + + Subclass of AvdModel. + + Args: + remote_peers: + Define remote peers of the EVPN VXLAN Gateway. + If the hostname can be found in the inventory, + ip_address and BGP ASN will be automatically populated. Manual override takes precedence. + If the + peer's hostname can not be found in the inventory, ip_address and bgp_as must be defined. + + + Subclass + of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + evpn_l2: + Enable EVPN Gateway functionality for route-types 2 (MAC-IP) and 3 (IMET). + + Subclass of AvdModel. + evpn_l3: + Enable EVPN Gateway functionality for route-type 5 (IP-PREFIX). + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class IpvpnGateway(AvdModel): + """Subclass of AvdModel.""" + + class AddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AddressFamilies._item_type = str + + class RemotePeersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hostname": {"type": str}, + "ip_address": {"type": str}, + "bgp_as": {"type": str}, + "_custom_data": {"type": dict}, + } + hostname: str + """Hostname of remote IPVPN Peer.""" + ip_address: str + """Peering IP of remote IPVPN Peer.""" + bgp_as: str + """ + Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For + asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted + as a float number. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: str | UndefinedType = Undefined, + ip_address: str | UndefinedType = Undefined, + bgp_as: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemotePeersItem. + + + Subclass of AvdModel. + + Args: + hostname: Hostname of remote IPVPN Peer. + ip_address: Peering IP of remote IPVPN Peer. + bgp_as: + Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For + asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted + as a float number. + _custom_data: _custom_data + + """ + + class RemotePeers(AvdIndexedList[str, RemotePeersItem]): + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + + _primary_key: ClassVar[str] = "hostname" + + RemotePeers._item_type = RemotePeersItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "evpn_domain_id": {"type": str, "default": "65535:1"}, + "ipvpn_domain_id": {"type": str, "default": "65535:2"}, + "enable_d_path": {"type": bool, "default": True}, + "maximum_routes": {"type": int, "default": 0}, + "local_as": {"type": str}, + "address_families": {"type": AddressFamilies, "default": lambda cls: coerce_type(["vpn-ipv4"], target_type=cls)}, + "remote_peers": {"type": RemotePeers}, + "_custom_data": {"type": dict}, + } + enabled: bool + evpn_domain_id: str + """ + Domain ID to assign to EVPN address family for use with D-path. Format :. + + Default value: `"65535:1"` + """ + ipvpn_domain_id: str + """ + Domain ID to assign to IPVPN address families for use with D-path. Format :. + + Default value: `"65535:2"` + """ + enable_d_path: bool + """ + Enable D-path for use with BGP bestpath selection algorithm. + + Default value: `True` + """ + maximum_routes: int + """ + Maximum routes to accept from IPVPN remote peers. + + Default value: `0` + """ + local_as: str | None + """ + Local BGP AS applied to peering with IPVPN remote peers. + BGP AS <1-4294967295> or AS number in asdot + notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number. + """ + address_families: AddressFamilies + """ + IPVPN address families to enable for remote peers. + + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["vpn-ipv4"], target_type=cls)` + """ + remote_peers: RemotePeers + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + evpn_domain_id: str | UndefinedType = Undefined, + ipvpn_domain_id: str | UndefinedType = Undefined, + enable_d_path: bool | UndefinedType = Undefined, + maximum_routes: int | UndefinedType = Undefined, + local_as: str | None | UndefinedType = Undefined, + address_families: AddressFamilies | UndefinedType = Undefined, + remote_peers: RemotePeers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpvpnGateway. + + + Subclass of AvdModel. + + Args: + enabled: enabled + evpn_domain_id: Domain ID to assign to EVPN address family for use with D-path. Format :. + ipvpn_domain_id: Domain ID to assign to IPVPN address families for use with D-path. Format :. + enable_d_path: Enable D-path for use with BGP bestpath selection algorithm. + maximum_routes: Maximum routes to accept from IPVPN remote peers. + local_as: + Local BGP AS applied to peering with IPVPN remote peers. + BGP AS <1-4294967295> or AS number in asdot + notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number. + address_families: + IPVPN address families to enable for remote peers. + + Subclass of AvdList with `str` items. + remote_peers: Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + _custom_data: _custom_data + + """ + + class MlagInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MlagInterfaces._item_type = str + + class OverlayAddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + OverlayAddressFamilies._item_type = str + + class MplsRouteReflectors(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MplsRouteReflectors._item_type = str + + class Ptp(AvdModel): + """Subclass of AvdModel.""" + + class Dscp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"general_messages": {"type": int}, "event_messages": {"type": int}, "_custom_data": {"type": dict}} + general_messages: int | None + event_messages: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + general_messages: int | None | UndefinedType = Undefined, + event_messages: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dscp. + + + Subclass of AvdModel. + + Args: + general_messages: general_messages + event_messages: event_messages + _custom_data: _custom_data + + """ + + class Monitor(AvdModel): + """Subclass of AvdModel.""" + + class Threshold(AvdModel): + """Subclass of AvdModel.""" + + class Drop(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "offset_from_master": {"type": int}, + "mean_path_delay": {"type": int}, + "_custom_data": {"type": dict}, + } + offset_from_master: int | None + mean_path_delay: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + offset_from_master: int | None | UndefinedType = Undefined, + mean_path_delay: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Drop. + + + Subclass of AvdModel. + + Args: + offset_from_master: offset_from_master + mean_path_delay: mean_path_delay + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "offset_from_master": {"type": int, "default": 250}, + "mean_path_delay": {"type": int, "default": 1500}, + "drop": {"type": Drop}, + "_custom_data": {"type": dict}, + } + offset_from_master: int + """Default value: `250`""" + mean_path_delay: int + """Default value: `1500`""" + drop: Drop + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + offset_from_master: int | UndefinedType = Undefined, + mean_path_delay: int | UndefinedType = Undefined, + drop: Drop | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Threshold. + + + Subclass of AvdModel. + + Args: + offset_from_master: offset_from_master + mean_path_delay: mean_path_delay + drop: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MissingMessage(AvdModel): + """Subclass of AvdModel.""" + + class Intervals(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "announce": {"type": int}, + "follow_up": {"type": int}, + "sync": {"type": int}, + "_custom_data": {"type": dict}, + } + announce: int | None + follow_up: int | None + sync: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + announce: int | None | UndefinedType = Undefined, + follow_up: int | None | UndefinedType = Undefined, + sync: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Intervals. + + + Subclass of AvdModel. + + Args: + announce: announce + follow_up: follow_up + sync: sync + _custom_data: _custom_data + + """ + + class SequenceIds(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "announce": {"type": int, "default": 3}, + "delay_resp": {"type": int, "default": 3}, + "follow_up": {"type": int, "default": 3}, + "sync": {"type": int, "default": 3}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + announce: int + """Default value: `3`""" + delay_resp: int + """Default value: `3`""" + follow_up: int + """Default value: `3`""" + sync: int + """Default value: `3`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + announce: int | UndefinedType = Undefined, + delay_resp: int | UndefinedType = Undefined, + follow_up: int | UndefinedType = Undefined, + sync: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceIds. + + + Subclass of AvdModel. + + Args: + enabled: enabled + announce: announce + delay_resp: delay_resp + follow_up: follow_up + sync: sync + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "intervals": {"type": Intervals}, + "sequence_ids": {"type": SequenceIds}, + "_custom_data": {"type": dict}, + } + intervals: Intervals + """Subclass of AvdModel.""" + sequence_ids: SequenceIds + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + intervals: Intervals | UndefinedType = Undefined, + sequence_ids: SequenceIds | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingMessage. + + + Subclass of AvdModel. + + Args: + intervals: Subclass of AvdModel. + sequence_ids: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "threshold": {"type": Threshold}, + "missing_message": {"type": MissingMessage}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + threshold: Threshold + """Subclass of AvdModel.""" + missing_message: MissingMessage + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + threshold: Threshold | UndefinedType = Undefined, + missing_message: MissingMessage | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Monitor. + + + Subclass of AvdModel. + + Args: + enabled: enabled + threshold: Subclass of AvdModel. + missing_message: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "profile": {"type": str}, + "mlag": {"type": bool, "default": False}, + "domain": {"type": int, "default": 127}, + "priority1": {"type": int}, + "priority2": {"type": int}, + "auto_clock_identity": {"type": bool}, + "clock_identity_prefix": {"type": str, "default": "00:1C:73"}, + "clock_identity": {"type": str}, + "source_ip": {"type": str}, + "mode": {"type": str, "default": "boundary"}, + "mode_one_step": {"type": bool, "default": False}, + "ttl": {"type": int}, + "forward_unicast": {"type": bool, "default": False}, + "dscp": {"type": Dscp}, + "monitor": {"type": Monitor}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + profile: str | None + """ + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + """ + mlag: bool + """ + Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be + configured on the MLAG peer-link port-channel. + + Default value: `False` + """ + domain: int + """Default value: `127`""" + priority1: int | None + """default -> automatically set based on node_type.""" + priority2: int | None + """default -> (node_id modulus 256).""" + auto_clock_identity: bool | None + """ + If you prefer to have PTP clock identity be the system MAC-address of the switch, which is the + default EOS behaviour, simply disable the automatic PTP clock identity. + default -> + (clock_identity_prefix = 00:1C:73 (default)) + (PTP priority 1 as HEX) + ":00:" + (PTP priority 2 as + HEX). + """ + clock_identity_prefix: str + """ + PTP clock idetentiy 3-byte prefix. i.e. "01:02:03". + By default the 3-byte prefix is "00:1C:73". + This + can be overridden if auto_clock_identity is set to true (which is the default). + + Default value: `"00:1C:73"` + """ + clock_identity: str | None + """Set PTP clock identity manually. 6-byte value i.e. "01:02:03:04:05:06".""" + source_ip: str | None + """ + By default in EOS, PTP packets are sourced with an IP address from the routed port or from the + relevant SVI, which is the recommended behaviour. + This can be set manually if required, for example, + to a value of "10.1.2.3". + """ + mode: Literal["boundary"] + """Default value: `"boundary"`""" + mode_one_step: bool + """Default value: `False`""" + ttl: int | None + forward_unicast: bool + """ + Enable PTP unicast forwarding. + + Default value: `False` + """ + dscp: Dscp + """Subclass of AvdModel.""" + monitor: Monitor + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + profile: str | None | UndefinedType = Undefined, + mlag: bool | UndefinedType = Undefined, + domain: int | UndefinedType = Undefined, + priority1: int | None | UndefinedType = Undefined, + priority2: int | None | UndefinedType = Undefined, + auto_clock_identity: bool | None | UndefinedType = Undefined, + clock_identity_prefix: str | UndefinedType = Undefined, + clock_identity: str | None | UndefinedType = Undefined, + source_ip: str | None | UndefinedType = Undefined, + mode: Literal["boundary"] | UndefinedType = Undefined, + mode_one_step: bool | UndefinedType = Undefined, + ttl: int | None | UndefinedType = Undefined, + forward_unicast: bool | UndefinedType = Undefined, + dscp: Dscp | UndefinedType = Undefined, + monitor: Monitor | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ptp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + profile: + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + mlag: + Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be + configured on the MLAG peer-link port-channel. + domain: domain + priority1: default -> automatically set based on node_type. + priority2: default -> (node_id modulus 256). + auto_clock_identity: + If you prefer to have PTP clock identity be the system MAC-address of the switch, which is the + default EOS behaviour, simply disable the automatic PTP clock identity. + default -> + (clock_identity_prefix = 00:1C:73 (default)) + (PTP priority 1 as HEX) + ":00:" + (PTP priority 2 as + HEX). + clock_identity_prefix: + PTP clock idetentiy 3-byte prefix. i.e. "01:02:03". + By default the 3-byte prefix is "00:1C:73". + This + can be overridden if auto_clock_identity is set to true (which is the default). + clock_identity: Set PTP clock identity manually. 6-byte value i.e. "01:02:03:04:05:06". + source_ip: + By default in EOS, PTP packets are sourced with an IP address from the routed port or from the + relevant SVI, which is the recommended behaviour. + This can be set manually if required, for example, + to a value of "10.1.2.3". + mode: mode + mode_one_step: mode_one_step + ttl: ttl + forward_unicast: Enable PTP unicast forwarding. + dscp: Subclass of AvdModel. + monitor: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class WanHa(AvdModel): + """Subclass of AvdModel.""" + + class HaInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + HaInterfaces._item_type = str + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "ipsec": {"type": bool, "default": True}, + "mtu": {"type": int, "default": 9194}, + "ha_interfaces": {"type": HaInterfaces}, + "ha_ipv4_pool": {"type": str}, + "max_ha_interfaces": {"type": int}, + "port_channel_id": {"type": int}, + "use_port_channel_for_direct_ha": {"type": bool, "default": True}, + "flow_tracking": {"type": FlowTracking}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group.""" + ipsec: bool + """ + Enable / Disable IPsec over HA path-group when HA is enabled. + + Default value: `True` + """ + mtu: int + """ + Set MTU on WAN HA interfaces. + + Default value: `9194` + """ + ha_interfaces: HaInterfaces + """ + Local WAN HA interfaces + Overwrite the default behavior which is to pick all the `uplink_interfaces`. + Can be used to filter uplink interfaces when there are multiple uplinks. + Limitations: + Either all + interfaces must be uplinks or all interfaces must not be uplinks. + Only one interface is supported + for non uplinks. + + Subclass of AvdList with `str` items. + """ + ha_ipv4_pool: str | None + """ + IP address pool used for WAN HA connectivity. + IP is derived from the node ID. + Not used for uplink + interfaces. + """ + max_ha_interfaces: int | None + """ + Number of parallel links towards HA switches. + Can be used to reserve IP addresses for future + parallel HA links. + """ + port_channel_id: int | None + """Port-channel ID to use for direct HA.""" + use_port_channel_for_direct_ha: bool + """ + Enable or disable using a port-channel interface for direct HA when there is only one interface. + This feature was introduced in EOS 4.33.0F. + + Default value: `True` + """ + flow_tracking: FlowTracking + """ + Configures flow-tracking on the HA interfaces. Overrides `fabric_flow_tracking.wan_ha_links` + setting. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + ipsec: bool | UndefinedType = Undefined, + mtu: int | UndefinedType = Undefined, + ha_interfaces: HaInterfaces | UndefinedType = Undefined, + ha_ipv4_pool: str | None | UndefinedType = Undefined, + max_ha_interfaces: int | None | UndefinedType = Undefined, + port_channel_id: int | None | UndefinedType = Undefined, + use_port_channel_for_direct_ha: bool | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + WanHa. + + + Subclass of AvdModel. + + Args: + enabled: Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group. + ipsec: Enable / Disable IPsec over HA path-group when HA is enabled. + mtu: Set MTU on WAN HA interfaces. + ha_interfaces: + Local WAN HA interfaces + Overwrite the default behavior which is to pick all the `uplink_interfaces`. + Can be used to filter uplink interfaces when there are multiple uplinks. + Limitations: + Either all + interfaces must be uplinks or all interfaces must not be uplinks. + Only one interface is supported + for non uplinks. + + Subclass of AvdList with `str` items. + ha_ipv4_pool: + IP address pool used for WAN HA connectivity. + IP is derived from the node ID. + Not used for uplink + interfaces. + max_ha_interfaces: + Number of parallel links towards HA switches. + Can be used to reserve IP addresses for future + parallel HA links. + port_channel_id: Port-channel ID to use for direct HA. + use_port_channel_for_direct_ha: + Enable or disable using a port-channel interface for direct HA when there is only one interface. + This feature was introduced in EOS 4.33.0F. + flow_tracking: + Configures flow-tracking on the HA interfaces. Overrides `fabric_flow_tracking.wan_ha_links` + setting. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L3InterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "peer_as": {"type": str}, + "ipv4_prefix_list_in": {"type": str}, + "ipv4_prefix_list_out": {"type": str}, + "_custom_data": {"type": dict}, + } + peer_as: str + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + ipv4_prefix_list_in: str | None + """ + Prefix List Name. Accept routes for only these prefixes from the peer. + Required for wan interfaces. + """ + ipv4_prefix_list_out: str | None + """ + Prefix List Name. Advertise routes for only these prefixes. + If not specified, nothing would be + advertised. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + peer_as: str | UndefinedType = Undefined, + ipv4_prefix_list_in: str | None | UndefinedType = Undefined, + ipv4_prefix_list_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + peer_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + ipv4_prefix_list_in: + Prefix List Name. Accept routes for only these prefixes from the peer. + Required for wan interfaces. + ipv4_prefix_list_out: + Prefix List Name. Advertise routes for only these prefixes. + If not specified, nothing would be + advertised. + _custom_data: _custom_data + + """ + + class StaticRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "_custom_data": {"type": dict}} + prefix: str + """IPv4_network/Mask.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, prefix: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + StaticRoutesItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv4_network/Mask. + _custom_data: _custom_data + + """ + + class StaticRoutes(AvdList[StaticRoutesItem]): + """Subclass of AvdList with `StaticRoutesItem` items.""" + + StaticRoutes._item_type = StaticRoutesItem + + class CvPathfinderInternetExit(AvdModel): + """Subclass of AvdModel.""" + + class PoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "tunnel_interface_numbers": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Internet-exit policy name.""" + tunnel_interface_numbers: str | None + """ + Number range to use for Tunnel interfaces to an internet-exit service provider using this local + interface. + Examples: '1-3' or '100,200,300' + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + tunnel_interface_numbers: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PoliciesItem. + + + Subclass of AvdModel. + + Args: + name: Internet-exit policy name. + tunnel_interface_numbers: + Number range to use for Tunnel interfaces to an internet-exit service provider using this local + interface. + Examples: '1-3' or '100,200,300' + _custom_data: _custom_data + + """ + + class Policies(AvdIndexedList[str, PoliciesItem]): + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Policies._item_type = PoliciesItem + + _fields: ClassVar[dict] = {"policies": {"type": Policies}, "_custom_data": {"type": dict}} + policies: Policies + """ + List of Internet-exit policies using this interface as exit. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, policies: Policies | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + CvPathfinderInternetExit. + + + Subclass of AvdModel. + + Args: + policies: + List of Internet-exit policies using this interface as exit. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "profile": {"type": str}, + "name": {"type": str}, + "description": {"type": str}, + "ip_address": {"type": str}, + "dhcp_ip": {"type": str}, + "public_ip": {"type": str}, + "encapsulation_dot1q_vlan": {"type": int}, + "dhcp_accept_default_route": {"type": bool, "default": True}, + "enabled": {"type": bool, "default": True}, + "speed": {"type": str}, + "peer": {"type": str}, + "peer_interface": {"type": str}, + "peer_ip": {"type": str}, + "bgp": {"type": Bgp}, + "ipv4_acl_in": {"type": str}, + "ipv4_acl_out": {"type": str}, + "static_routes": {"type": StaticRoutes}, + "qos_profile": {"type": str}, + "wan_carrier": {"type": str}, + "wan_circuit_id": {"type": str}, + "connected_to_pathfinder": {"type": bool, "default": True}, + "cv_pathfinder_internet_exit": {"type": CvPathfinderInternetExit}, + "raw_eos_cli": {"type": str}, + "flow_tracking": {"type": FlowTracking}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + profile: str | None + """L3 interface profile name. Profile defined under `l3_interface_profiles`.""" + name: str + """ + Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. + For a + subinterface, the parent physical interface is automatically created. + """ + description: str | None + """ + Interface description. + If not set a default description will be configured with '[[ + ]]'. + """ + ip_address: str | None + """Node IPv4 address/Mask or 'dhcp'.""" + dhcp_ip: str | None + """ + When the `ip_address` is `dhcp`, this optional field allows to indicate the expected + IPv4 address + (without mask) to be allocated on the interface if known. + This is not rendered in the configuration + but can be used for substitution of 'interface_ip' in the Access-list + set under `ipv4_acl_in` and + `ipv4_acl_out`. + """ + public_ip: str | None + """ + Node IPv4 address (no mask). + + This is used to get the public IP (if known) when the device is behind + NAT. + This is only used for `wan_rr` routers (AutoVPN RRs and Pathfinders) to determine the Public IP + with the following preference: + `wan_route_servers.path_groups.interfaces.ip_address` + -> + `l3_interfaces.public_ip` + -> `l3_interfaces.ip_address` + + The determined Public IP is used + by WAN routers when peering with this interface. + """ + encapsulation_dot1q_vlan: int | None + """ + For subinterfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + """ + dhcp_accept_default_route: bool + """ + Accept a default route from DHCP if `ip_address` is set to `dhcp`. + + Default value: `True` + """ + enabled: bool + """ + Enable or Shutdown the interface. + + Default value: `True` + """ + speed: str | None + """ + Speed should be set in the format `` or `forced ` or `auto + `. + """ + peer: str | None + """The peer device name. Used for description and documentation.""" + peer_interface: str | None + """The peer device interface. Used for description and documentation.""" + peer_ip: str | None + """ + The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true + and `ip` is an IP address. + """ + bgp: Bgp + """ + Enforce IPv4 BGP peering for the peer + + Subclass of AvdModel. + """ + ipv4_acl_in: str | None + """ + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + Required + for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under + `wan_carriers`. + """ + ipv4_acl_out: str | None + """ + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + """ + static_routes: StaticRoutes + """ + Configure IPv4 static routes pointing to `peer_ip`. + + Subclass of AvdList with `StaticRoutesItem` + items. + """ + qos_profile: str | None + """QOS service profile.""" + wan_carrier: str | None + """ + The WAN carrier this interface is connected to. + This is used to infer the path-groups in which this + interface should be configured. + Unless the carrier is marked as 'trusted' under `wan_carriers`, + `ipv4_acl_in` is also required on all WAN interfaces. + """ + wan_circuit_id: str | None + """ + The WAN circuit ID for this interface. + This is not rendered in the configuration but used for WAN + designs. + """ + connected_to_pathfinder: bool + """ + For a WAN interface (`wan_carrier` is set), allow to disable the static tunnel towards Pathfinders. + + Default value: `True` + """ + cv_pathfinder_internet_exit: CvPathfinderInternetExit + """ + PREVIEW: This key is in preview mode + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the interface in the final EOS configuration.""" + flow_tracking: FlowTracking + """ + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + """ + structured_config: StructuredConfig + """ + Custom structured config for the Ethernet interface. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | None | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + dhcp_ip: str | None | UndefinedType = Undefined, + public_ip: str | None | UndefinedType = Undefined, + encapsulation_dot1q_vlan: int | None | UndefinedType = Undefined, + dhcp_accept_default_route: bool | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + speed: str | None | UndefinedType = Undefined, + peer: str | None | UndefinedType = Undefined, + peer_interface: str | None | UndefinedType = Undefined, + peer_ip: str | None | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + ipv4_acl_in: str | None | UndefinedType = Undefined, + ipv4_acl_out: str | None | UndefinedType = Undefined, + static_routes: StaticRoutes | UndefinedType = Undefined, + qos_profile: str | None | UndefinedType = Undefined, + wan_carrier: str | None | UndefinedType = Undefined, + wan_circuit_id: str | None | UndefinedType = Undefined, + connected_to_pathfinder: bool | UndefinedType = Undefined, + cv_pathfinder_internet_exit: CvPathfinderInternetExit | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L3InterfacesItem. + + + Subclass of AvdModel. + + Args: + profile: L3 interface profile name. Profile defined under `l3_interface_profiles`. + name: + Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. + For a + subinterface, the parent physical interface is automatically created. + description: + Interface description. + If not set a default description will be configured with '[[ + ]]'. + ip_address: Node IPv4 address/Mask or 'dhcp'. + dhcp_ip: + When the `ip_address` is `dhcp`, this optional field allows to indicate the expected + IPv4 address + (without mask) to be allocated on the interface if known. + This is not rendered in the configuration + but can be used for substitution of 'interface_ip' in the Access-list + set under `ipv4_acl_in` and + `ipv4_acl_out`. + public_ip: + Node IPv4 address (no mask). + + This is used to get the public IP (if known) when the device is behind + NAT. + This is only used for `wan_rr` routers (AutoVPN RRs and Pathfinders) to determine the Public IP + with the following preference: + `wan_route_servers.path_groups.interfaces.ip_address` + -> + `l3_interfaces.public_ip` + -> `l3_interfaces.ip_address` + + The determined Public IP is used + by WAN routers when peering with this interface. + encapsulation_dot1q_vlan: + For subinterfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + dhcp_accept_default_route: Accept a default route from DHCP if `ip_address` is set to `dhcp`. + enabled: Enable or Shutdown the interface. + speed: + Speed should be set in the format `` or `forced ` or `auto + `. + peer: The peer device name. Used for description and documentation. + peer_interface: The peer device interface. Used for description and documentation. + peer_ip: + The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true + and `ip` is an IP address. + bgp: + Enforce IPv4 BGP peering for the peer + + Subclass of AvdModel. + ipv4_acl_in: + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + Required + for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under + `wan_carriers`. + ipv4_acl_out: + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + static_routes: + Configure IPv4 static routes pointing to `peer_ip`. + + Subclass of AvdList with `StaticRoutesItem` + items. + qos_profile: QOS service profile. + wan_carrier: + The WAN carrier this interface is connected to. + This is used to infer the path-groups in which this + interface should be configured. + Unless the carrier is marked as 'trusted' under `wan_carriers`, + `ipv4_acl_in` is also required on all WAN interfaces. + wan_circuit_id: + The WAN circuit ID for this interface. + This is not rendered in the configuration but used for WAN + designs. + connected_to_pathfinder: For a WAN interface (`wan_carrier` is set), allow to disable the static tunnel towards Pathfinders. + cv_pathfinder_internet_exit: + PREVIEW: This key is in preview mode + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the interface in the final EOS configuration. + flow_tracking: + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + structured_config: + Custom structured config for the Ethernet interface. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): + """Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + L3Interfaces._item_type = L3InterfacesItem + + _fields: ClassVar[dict] = { + "id": {"type": int}, + "platform": {"type": str}, + "mac_address": {"type": str}, + "system_mac_address": {"type": str}, + "serial_number": {"type": str}, + "rack": {"type": str}, + "mgmt_ip": {"type": str}, + "mgmt_gateway": {"type": str}, + "ipv6_mgmt_ip": {"type": str}, + "ipv6_mgmt_gateway": {"type": str}, + "mgmt_interface": {"type": str}, + "link_tracking": {"type": LinkTracking}, + "lacp_port_id_range": {"type": LacpPortIdRange}, + "always_configure_ip_routing": {"type": bool, "default": False}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "uplink_type": {"type": str}, + "uplink_ipv4_pool": {"type": str}, + "uplink_interfaces": {"type": UplinkInterfaces}, + "uplink_switch_interfaces": {"type": UplinkSwitchInterfaces}, + "uplink_switches": {"type": UplinkSwitches}, + "uplink_interface_speed": {"type": str}, + "uplink_switch_interface_speed": {"type": str}, + "uplink_mtu": {"type": int}, + "max_uplink_switches": {"type": int}, + "max_parallel_uplinks": {"type": int, "default": 1}, + "uplink_bfd": {"type": bool, "default": False}, + "uplink_native_vlan": {"type": int}, + "uplink_ptp": {"type": UplinkPtp}, + "uplink_macsec": {"type": UplinkMacsec}, + "uplink_port_channel_id": {"type": int}, + "uplink_switch_port_channel_id": {"type": int}, + "uplink_structured_config": {"type": dict}, + "mlag_port_channel_structured_config": {"type": MlagPortChannelStructuredConfig}, + "mlag_peer_vlan_structured_config": {"type": MlagPeerVlanStructuredConfig}, + "mlag_peer_l3_vlan_structured_config": {"type": MlagPeerL3VlanStructuredConfig}, + "short_esi": {"type": str}, + "isis_system_id_prefix": {"type": str}, + "isis_maximum_paths": {"type": int}, + "is_type": {"type": str}, + "node_sid_base": {"type": int, "default": 0}, + "loopback_ipv4_pool": {"type": str}, + "loopback_ipv4_address": {"type": str}, + "vtep_loopback_ipv4_pool": {"type": str}, + "vtep_loopback_ipv4_address": {"type": str}, + "loopback_ipv4_offset": {"type": int, "default": 0}, + "loopback_ipv6_pool": {"type": str}, + "loopback_ipv6_offset": {"type": int, "default": 0}, + "vtep": {"type": bool}, + "vtep_loopback": {"type": str}, + "bgp_as": {"type": str}, + "bgp_defaults": {"type": BgpDefaults}, + "evpn_role": {"type": str}, + "evpn_route_servers": {"type": EvpnRouteServers}, + "evpn_services_l2_only": {"type": bool, "default": False}, + "filter": {"type": Filter}, + "igmp_snooping_enabled": {"type": bool}, + "evpn_gateway": {"type": EvpnGateway}, + "ipvpn_gateway": {"type": IpvpnGateway}, + "mlag": {"type": bool, "default": True}, + "mlag_dual_primary_detection": {"type": bool, "default": False}, + "mlag_ibgp_origin_incomplete": {"type": bool, "default": True}, + "mlag_interfaces": {"type": MlagInterfaces}, + "mlag_interfaces_speed": {"type": str}, + "mlag_peer_l3_vlan": {"type": int, "default": 4093}, + "mlag_peer_l3_ipv4_pool": {"type": str}, + "mlag_peer_vlan": {"type": int, "default": 4094}, + "mlag_peer_link_allowed_vlans": {"type": str}, + "mlag_peer_address_family": {"type": str, "default": "ipv4"}, + "mlag_peer_ipv4_pool": {"type": str}, + "mlag_peer_ipv6_pool": {"type": str}, + "mlag_port_channel_id": {"type": int}, + "mlag_domain_id": {"type": str}, + "spanning_tree_mode": {"type": str}, + "spanning_tree_priority": {"type": int, "default": 32768}, + "spanning_tree_root_super": {"type": bool, "default": False}, + "virtual_router_mac_address": {"type": str}, + "inband_mgmt_interface": {"type": str}, + "inband_mgmt_vlan": {"type": int, "default": 4092}, + "inband_mgmt_subnet": {"type": str}, + "inband_mgmt_ip": {"type": str}, + "inband_mgmt_gateway": {"type": str}, + "inband_mgmt_ipv6_address": {"type": str}, + "inband_mgmt_ipv6_subnet": {"type": str}, + "inband_mgmt_ipv6_gateway": {"type": str}, + "inband_mgmt_description": {"type": str, "default": "Inband Management"}, + "inband_mgmt_vlan_name": {"type": str, "default": "INBAND_MGMT"}, + "inband_mgmt_vrf": {"type": str, "default": "default"}, + "inband_mgmt_mtu": {"type": int, "default": 1500}, + "inband_ztp": {"type": bool, "default": False}, + "inband_ztp_lacp_fallback_delay": {"type": int, "default": 30}, + "mpls_overlay_role": {"type": str}, + "overlay_address_families": {"type": OverlayAddressFamilies}, + "mpls_route_reflectors": {"type": MplsRouteReflectors}, + "bgp_cluster_id": {"type": str}, + "ptp": {"type": Ptp}, + "wan_role": {"type": str}, + "cv_pathfinder_transit_mode": {"type": str}, + "cv_pathfinder_region": {"type": str}, + "cv_pathfinder_site": {"type": str}, + "wan_ha": {"type": WanHa}, + "dps_mss_ipv4": {"type": str, "default": "auto"}, + "l3_interfaces": {"type": L3Interfaces}, + "data_plane_cpu_allocation_max": {"type": int}, + "flow_tracker_type": {"type": str}, + "_custom_data": {"type": dict}, + } + id: int | None + """Unique identifier used for IP addressing and other algorithms.""" + platform: str | None + """Arista platform family.""" + mac_address: str | None + """Leverage to document management interface mac address.""" + system_mac_address: str | None + """ + System MAC Address in this following format: "xx:xx:xx:xx:xx:xx". + Set to the same MAC address as + available in "show version" on the device. + "system_mac_address" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + """ + serial_number: str | None + """ + Set to the Serial Number of the device. + Only used for documentation purpose in the fabric + documentation and part of the structured_config. + "serial_number" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + """ + rack: str | None + """Rack that the switch is located in (only used in snmp_settings location).""" + mgmt_ip: str | None + """Node management interface IPv4 address.""" + mgmt_gateway: str | None + """ + This key sets the management gateway for the device. It takes precedence over the global + `mgmt_gateway`. + """ + ipv6_mgmt_ip: str | None + """Node management interface IPv6 address.""" + ipv6_mgmt_gateway: str | None + """ + This key sets the ipv6 management gateway for the device. It takes precedence over the global + `ipv6_mgmt_gateway`. + """ + mgmt_interface: str | None + """ + Management Interface Name. + Default -> platform_management_interface -> mgmt_interface -> + "Management1". + """ + link_tracking: LinkTracking + """ + This configures the Link Tracking Group on a switch as well as adds the p2p-uplinks of the switch as + the upstream interfaces. + Useful in EVPN multhoming designs. + + + Subclass of AvdModel. + """ + lacp_port_id_range: LacpPortIdRange + """ + This will generate the "lacp port-id range", "begin" and "end" values based on node "id" and the + number of nodes in the "node_group". + Unique LACP port-id ranges are recommended for EVPN Multihoming + designs. + + + Subclass of AvdModel. + """ + always_configure_ip_routing: bool + """ + Force configuration of "ip routing" even on L2 devices. + Use this to retain behavior of AVD versions + below 4.0.0. + + Default value: `False` + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the root level of the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + """ + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None + """ + Override the default `uplink_type` set at the `node_type_key` level. + `uplink_type` must be "p2p" if + `vtep` or `underlay_router` is true for the `node_type_key` definition. + """ + uplink_ipv4_pool: str | None + """IPv4 subnet to use to connect to uplink switches.""" + uplink_interfaces: UplinkInterfaces + """ + Local uplink interfaces. + Each list item supports range syntax that can be expanded into a list of + interfaces. + If uplink_interfaces is not defined, platform-specific defaults (defined under + default_interfaces) will be used instead. + Please note that default_interfaces are not defined by + default, you should define these yourself. + + + Subclass of AvdList with `str` items. + """ + uplink_switch_interfaces: UplinkSwitchInterfaces + """ + Interfaces located on uplink switches. + + Subclass of AvdList with `str` items. + """ + uplink_switches: UplinkSwitches + """Subclass of AvdList with `str` items.""" + uplink_interface_speed: str | None + """ + Set point-to-Point interface speed and will apply to uplink interfaces on both ends. + (Uplink switch + interface speed can be overridden with `uplink_switch_interface_speed`). + Speed should be set in the + format `` or `forced ` or `auto `. + """ + uplink_switch_interface_speed: str | None + """ + 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: int | None + """Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting.""" + max_uplink_switches: int | None + """ + 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: 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 + """ + Enable bfd on uplink interfaces. + + Default value: `False` + """ + uplink_native_vlan: int | None + """ + 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: UplinkPtp + """ + Enable PTP on all infrastructure links. + + Subclass of AvdModel. + """ + uplink_macsec: UplinkMacsec + """ + Enable MacSec on all uplinks. + + Subclass of AvdModel. + """ + uplink_port_channel_id: int | None + """ + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink Port-channel + ID will be set to the number of the lowest member interface defined under `uplink_interfaces`. + For + example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ Eth11/1, Eth22/1 ] -> ID 111 + For + MLAG port-channels ID will be based on the lowest member interface on the first MLAG switch. + This + option overrides the default behavior and statically sets the local Port-channel ID. + Note! Make sure + the ID is unique and does not overlap with autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between 1 and 2000 and both MLAG switches must have the same + value. + """ + uplink_switch_port_channel_id: int | None + """ + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink switch Port- + channel ID will be set to the number of the first interface defined under + `uplink_switch_interfaces`. + For example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ + Eth11/1, Eth22/1 ] -> ID 111 + For MLAG port-channels ID will be based on the lowest member interface + on the first MLAG switch. + This option overrides the default behavior and statically sets the Port- + channel ID on the uplink switch. + Note! Make sure the ID is unique and does not overlap with + autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between + 1 and 2000 and both MLAG switches must have the same value. + """ + uplink_structured_config: dict + """ + Custom structured config applied to "uplink_interfaces", and "uplink_switch_interfaces". + When + uplink_type == "p2p", custom structured config added under ethernet_interfaces.[name=] + for eos_cli_config_gen overrides the settings on the ethernet interface level. + When uplink_type == + "port-channel", custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen overrides the settings on the port-channel interface level. + "uplink_structured_config" is applied after "structured_config", so it can override + "structured_config" defined on node-level. + Note! The content of this dictionary is _not_ validated + by the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + """ + mlag_port_channel_structured_config: MlagPortChannelStructuredConfig + """ + Custom structured config applied to MLAG peer link port-channel id. + Added under + port_channel_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the + port-channel interface level. + "mlag_port_channel_structured_config" is applied after + "structured_config", so it can override "structured_config" defined on node-level. + + + Subclass of + AvdModel. + """ + mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig + """ + Custom structured config applied to MLAG Peer Link (control link) SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_vlan_structured_config" is applied after "structured_config", so it can + override "structured_config" defined on node-level. + + + Subclass of AvdModel. + """ + mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig + """ + Custom structured config applied to MLAG underlay L3 peering SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_l3_vlan_structured_config" is applied after "structured_config", so it + can override "structured_config" defined on node-level. + + + Subclass of AvdModel. + """ + short_esi: str | None + """ + short_esi only valid for l2leaf devices using port-channel uplink. + Setting short_esi to "auto" + generates the short_esi automatically using a hash of configuration elements. + < 0000:0000:0000 | + auto >. + """ + isis_system_id_prefix: str | None + """(4.4 hexadecimal).""" + isis_maximum_paths: int | None + """Number of path to configure in ECMP for ISIS.""" + is_type: Literal["level-1-2", "level-1", "level-2"] | None + """Overrides `isis_default_is_type`.""" + node_sid_base: int + """ + Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID. + + Default value: `0` + """ + loopback_ipv4_pool: str | None + """IPv4 subnet for Loopback0 allocation.""" + loopback_ipv4_address: str | None + """ + IPv4 address without mask for Loopback0. + When set, it takes precedence over `loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not catch duplicates. + """ + vtep_loopback_ipv4_pool: str | None + """IPv4 subnet for VTEP-Loopback allocation.""" + vtep_loopback_ipv4_address: str | None + """ + IPv4 address without mask for VTEP-Loopback. + When set, it takes precedence over + `vtep_loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not + catch duplicates. + """ + loopback_ipv4_offset: int + """ + Offset all assigned loopback IP addresses. + Required when the < loopback_ipv4_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid over-lapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv4_offset: < total # spine switches > or vice versa. + + Default value: `0` + """ + loopback_ipv6_pool: str | None + """IPv6 subnet for Loopback0 allocation.""" + loopback_ipv6_offset: int + """ + Offset all assigned loopback IPv6 addresses. + Required when the < loopback_ipv6_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid overlapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv6_offset: < total # spine switches > or vice versa. + + Default value: `0` + """ + vtep: bool | None + """ + Node is configured as a VTEP when applicable based on 'overlay_routing_protocol'. + Overrides VTEP + setting inherited from node_type_keys. + """ + vtep_loopback: str | None + """Set VXLAN source interface.""" + bgp_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + Required with eBGP. + """ + bgp_defaults: BgpDefaults + """ + List of EOS commands to apply to BGP daemon. + + Subclass of AvdList with `str` items. + """ + evpn_role: Literal["client", "server", "none"] | None + """ + Acting role in EVPN control plane. + Default is set in node_type definition from node_type_keys. + """ + evpn_route_servers: EvpnRouteServers + """ + List of nodes acting as EVPN Route-Servers / Route-Reflectors. + + Subclass of AvdList with `str` + items. + """ + evpn_services_l2_only: bool + """ + Possibility to prevent configuration of Tenant VRFs and SVIs. + Override node definition + "network_services_l3" from node_type_keys. + This allows support for centralized routing. + + Default value: `False` + """ + filter: Filter + """ + Filter L3 and L2 network services based on tenant and tags (and operation filter). + If filter is not + defined it will default to all. + + + Subclass of AvdModel. + """ + igmp_snooping_enabled: bool | None + """Activate or deactivate IGMP snooping on device level.""" + evpn_gateway: EvpnGateway + """ + Node is acting as EVPN Multi-Domain Gateway. + New BGP peer-group is generated between EVPN GWs in + different domains or between GWs and Route Servers. + Name can be changed under + "bgp_peer_groups.evpn_overlay_core" variable. + L3 rechability for different EVPN GWs must be already + in place, it is recommended to use DCI & L3 Edge if Route Servers and GWs are not defined under the + same Ansible inventory. + + + Subclass of AvdModel. + """ + ipvpn_gateway: IpvpnGateway + """ + Node is acting as IP-VPN Gateway for EVPN to MPLS-IP-VPN Interworking. The BGP peer group used for + this is "bgp_peer_groups.ipvpn_gateway_peers". + L3 Reachability is required for this to work, the + preferred method to establish underlay connectivity is to use core_interfaces. + + + Subclass of + AvdModel. + """ + mlag: bool + """ + Enable / Disable auto MLAG, when two nodes are defined in node group. + + Default value: `True` + """ + mlag_dual_primary_detection: bool + """ + Enable / Disable MLAG dual primary detection. + + Default value: `False` + """ + mlag_ibgp_origin_incomplete: bool + """ + Set origin of routes received from MLAG iBGP peer to incomplete. + The purpose is to optimize routing + for leaf loopbacks from spine perspective and + avoid suboptimal routing via peerlink for control + plane traffic. + + Default value: `True` + """ + mlag_interfaces: MlagInterfaces + """ + Each list item supports range syntax that can be expanded into a list of interfaces. + Required when + MLAG leafs are present in the topology. + + + Subclass of AvdList with `str` items. + """ + mlag_interfaces_speed: str | None + """ + Set MLAG interface speed. + Speed should be set in the format `` or `forced + ` or `auto `. + """ + mlag_peer_l3_vlan: int + """ + Underlay L3 peering SVI interface id. + If set to 0 or the same vlan as mlag_peer_vlan, the + mlag_peer_vlan will be used for L3 peering. + + Default value: `4093` + """ + mlag_peer_l3_ipv4_pool: str | None + """ + IP address pool used for MLAG underlay L3 peering. IP is derived from the node id. + Required when + MLAG leafs present in topology and they are using a separate L3 peering VLAN. + """ + mlag_peer_vlan: int + """ + MLAG Peer Link (control link) SVI interface id. + + Default value: `4094` + """ + mlag_peer_link_allowed_vlans: str | None + mlag_peer_address_family: Literal["ipv4", "ipv6"] + """ + IP address family used to establish MLAG Peer Link (control link). + `ipv6` requires EOS version + 4.31.1F or higher. + Note: `ipv6` is not supported in combination with a common MLAG peer link VLAN + (ex. `mlag_peer_l3_vlan` set to 4094). + + Default value: `"ipv4"` + """ + mlag_peer_ipv4_pool: str | None + """ + IPv4 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv4` (default). + """ + mlag_peer_ipv6_pool: str | None + """ + IPv6 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv6`. + """ + mlag_port_channel_id: int | None + """ + If not set, the mlag port-channel id is generated based on the digits of the first interface present + in 'mlag_interfaces'. + Valid port-channel id numbers are < 1-2000 > for EOS < 4.25.0F and < 1 - + 999999 > for EOS >= 4.25.0F. + """ + mlag_domain_id: str | None + """MLAG Domain ID. If not set the node group name (Set with "group" key) will be used.""" + spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None + spanning_tree_priority: int + """ + Spanning-tree priority configured for the selected mode. + For `rapid-pvst` the priority can also be + set per VLAN under network services. + + Default value: `32768` + """ + spanning_tree_root_super: bool + """Default value: `False`""" + virtual_router_mac_address: str | None + """Virtual router mac address for anycast gateway.""" + inband_mgmt_interface: str | None + """ + Pointer to interface used for inband management. + All configuration must be done using other data + models like network services or structured_config. + 'inband_mgmt_interface' is only used to refer to + this interface as source in various management protocol settings (future feature). + + On L2 switches, + this defaults to Vlan if either 'inband_mgmt_subnet' or 'inband_mgmt_ip' is set. + """ + inband_mgmt_vlan: int + """ + VLAN number used for inband management on L2 switches (switches using port-channel trunks as + uplinks). + When using 'inband_mgmt_subnet' the VLAN and SVIs will be created automatically on this + switch as well as all 'uplink_switches'. + When using 'inband_mgmt_ip' the VLAN and SVI will only be + created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be + created using network services data models. + + Default value: `4092` + """ + inband_mgmt_subnet: str | None + """ + Optional IP subnet assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ip virtual-router" and host-route injection based on + ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + + 3 + + GW on l2leafs : + 1 + Assign range larger than total l2leafs + 5 + Setting is ignored if 'inband_mgmt_ip' is set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + """ + inband_mgmt_ip: str | None + """ + IP address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_subnet', hence all behavior of 'inband_mgmt_subnet' is removed. + + If this is set the + VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN and SVI on + the parent switches must be created using network services data models. + + This setting is applicable + to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_gateway: str | None + """ + Default gateway configured in the 'inband_mgmt_vrf' when using 'inband_mgmt_ip'. Otherwise gateway + is derived from 'inband_mgmt_subnet' if set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_address: str | None + """ + IPv6 address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_ipv6_subnet', hence the configuration of 'inband_mgmt_ipv6_subnet' is ignored. + + If this + is set the VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN + and SVI on the parent switches must be created using network services data models. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_subnet: str | None + """ + Optional IPv6 prefix assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ipv6 virtual-router" and host-route injection based + on ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN + extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + 3 + + GW on l2leafs : + 1 + Assign range larger than + total l2leafs + 5 + + Setting is ignored if 'inband_mgmt_ipv6_address' is set. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_gateway: str | None + """ + Default gateway configured in the 'inband_mgmt_vrf'. + Used when `inband_mgmt_ipv6_address` is set. + Ignored when 'inband_mgmt_ipv6_subnet' is set (first IP in subnet used as gateway). + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_description: str + """ + Description configured on the Inband Management SVI. + + This setting is only applied on the devices + where it is set, it does not automatically affect any parent/child devices configuration, so it must + be set on each applicable node/node-group/node-type as needed. + + Default value: `"Inband Management"` + """ + inband_mgmt_vlan_name: str + """ + Name configured on the Inband Management VLAN. + This setting is only applied on the devices where it + is set, it does not automatically affect any parent/child devices configuration, so it must be set + on each applicable node/node-group/node-type as needed. + + Default value: `"INBAND_MGMT"` + """ + inband_mgmt_vrf: str + """ + VRF configured on the Inband Management Interface. + The VRF is created if not already created by + other means. + This setting is only applied on the devices where it is set, it does not automatically + affect any parent/child devices configuration, so it must be set on each applicable node/node- + group/node-type as needed. + + Default value: `"default"` + """ + inband_mgmt_mtu: int + """ + MTU configured on the Inband Management Interface. + This setting is only applied on the devices where + it is set, it does not automatically affect any parent/child devices configuration, so it must be + set on each applicable node/node-group/node-type as needed. + + Default value: `1500` + """ + inband_ztp: bool + """ + Enable to configure upstream device with proper configuration to allow downstream devices to be + Zero-Touch-Provisioned over the uplink interfaces. + For L2 devices this setting also requires that + the `inband_mgmt_vlan` is set for the node. + + PREVIEW: Support for L3 devices is marked as "preview", + meaning the data models or generated configuration can change at any time. + + Default value: `False` + """ + inband_ztp_lacp_fallback_delay: int + """ + Set the LACP fallback timeout of the upstream device's port-channel towards the downstream inband + ZTP node. + This setting also requires that `inband_ztp` is set for the node. + + Default value: `30` + """ + mpls_overlay_role: Literal["client", "server", "none"] | None + """ + Set the default mpls overlay role. + Acting role in overlay control plane. + """ + overlay_address_families: OverlayAddressFamilies + """ + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + """ + mpls_route_reflectors: MplsRouteReflectors + """ + List of inventory hostname acting as MPLS route-reflectors. + + Subclass of AvdList with `str` items. + """ + bgp_cluster_id: str | None + """Set BGP cluster id.""" + ptp: Ptp + """Subclass of AvdModel.""" + wan_role: Literal["client", "server"] | None + """ + Override the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + """ + cv_pathfinder_transit_mode: Literal["region", "zone"] | None + """ + Configure the transit mode for a WAN client for CV Pathfinder designs + only when the `wan_mode` root + key is set to `cv_pathfinder`. + + 'zone' is currently not supported. + """ + cv_pathfinder_region: str | None + """ + The CV Pathfinder region name. + This key is required for WAN routers but optional for pathfinders. + The region name must be defined under 'cv_pathfinder_regions'. + """ + cv_pathfinder_site: str | None + """ + The CV Pathfinder site name. + This key is required for WAN routers but optional for pathfinders. + For + WAN routers and pathfinders with `cv_pathfinder_region`, the site name must be defined for the + relevant region under 'cv_pathfinder_regions'. + For pathfinders without `cv_pathfinder_region` set, + the site must be defined under `cv_pathfinder_global_sites`. + """ + wan_ha: WanHa + """ + PREVIEW: This key is currently not supported + + The key is supported only if `wan_mode` == `cv- + pathfinder`. + AutoVPN support is still to be determined. + + Maximum 2 devices supported by group for + HA. + + Subclass of AvdModel. + """ + dps_mss_ipv4: str + """ + IPv4 MSS value configured under "router path-selection" on WAN Devices. + + Default value: `"auto"` + """ + l3_interfaces: L3Interfaces + """ + L3 Interfaces to configure on the node. + Used to define the node for WAN interfaces when + `wan_carrier` is set. + + Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is + `name` (`str`). + """ + data_plane_cpu_allocation_max: int | None + """ + Set the maximum number of CPU used for the data plane. + This setting is useful on virtual Route + Reflectors and Pathfinders where more CPU cores should be allocated for control plane. + """ + flow_tracker_type: Literal["sampled", "hardware"] | None + """ + Set the flow tracker type. + Override the `default_flow_tracker_type`` set at the `node_type_key` + level. + `default_flow_tracker_type` default value is `sampled`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + id: int | None | UndefinedType = Undefined, + platform: str | None | UndefinedType = Undefined, + mac_address: str | None | UndefinedType = Undefined, + system_mac_address: str | None | UndefinedType = Undefined, + serial_number: str | None | UndefinedType = Undefined, + rack: str | None | UndefinedType = Undefined, + mgmt_ip: str | None | UndefinedType = Undefined, + mgmt_gateway: str | None | UndefinedType = Undefined, + ipv6_mgmt_ip: str | None | UndefinedType = Undefined, + ipv6_mgmt_gateway: str | None | UndefinedType = Undefined, + mgmt_interface: str | None | UndefinedType = Undefined, + link_tracking: LinkTracking | UndefinedType = Undefined, + lacp_port_id_range: LacpPortIdRange | UndefinedType = Undefined, + always_configure_ip_routing: bool | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None | UndefinedType = Undefined, + uplink_ipv4_pool: str | None | UndefinedType = Undefined, + uplink_interfaces: UplinkInterfaces | UndefinedType = Undefined, + uplink_switch_interfaces: UplinkSwitchInterfaces | UndefinedType = Undefined, + uplink_switches: UplinkSwitches | UndefinedType = Undefined, + uplink_interface_speed: str | None | UndefinedType = Undefined, + 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 | UndefinedType = Undefined, + uplink_bfd: bool | UndefinedType = Undefined, + uplink_native_vlan: int | None | UndefinedType = Undefined, + uplink_ptp: UplinkPtp | UndefinedType = Undefined, + uplink_macsec: UplinkMacsec | UndefinedType = Undefined, + uplink_port_channel_id: int | None | UndefinedType = Undefined, + uplink_switch_port_channel_id: int | None | UndefinedType = Undefined, + uplink_structured_config: dict | UndefinedType = Undefined, + mlag_port_channel_structured_config: MlagPortChannelStructuredConfig | UndefinedType = Undefined, + mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig | UndefinedType = Undefined, + mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig | UndefinedType = Undefined, + short_esi: str | None | UndefinedType = Undefined, + isis_system_id_prefix: str | None | UndefinedType = Undefined, + isis_maximum_paths: int | None | UndefinedType = Undefined, + is_type: Literal["level-1-2", "level-1", "level-2"] | None | UndefinedType = Undefined, + node_sid_base: int | UndefinedType = Undefined, + loopback_ipv4_pool: str | None | UndefinedType = Undefined, + loopback_ipv4_address: str | None | UndefinedType = Undefined, + vtep_loopback_ipv4_pool: str | None | UndefinedType = Undefined, + vtep_loopback_ipv4_address: str | None | UndefinedType = Undefined, + loopback_ipv4_offset: int | UndefinedType = Undefined, + loopback_ipv6_pool: str | None | UndefinedType = Undefined, + loopback_ipv6_offset: int | UndefinedType = Undefined, + vtep: bool | None | UndefinedType = Undefined, + vtep_loopback: str | None | UndefinedType = Undefined, + bgp_as: str | None | UndefinedType = Undefined, + bgp_defaults: BgpDefaults | UndefinedType = Undefined, + evpn_role: Literal["client", "server", "none"] | None | UndefinedType = Undefined, + evpn_route_servers: EvpnRouteServers | UndefinedType = Undefined, + evpn_services_l2_only: bool | UndefinedType = Undefined, + filter: Filter | UndefinedType = Undefined, + igmp_snooping_enabled: bool | None | UndefinedType = Undefined, + evpn_gateway: EvpnGateway | UndefinedType = Undefined, + ipvpn_gateway: IpvpnGateway | UndefinedType = Undefined, + mlag: bool | UndefinedType = Undefined, + mlag_dual_primary_detection: bool | UndefinedType = Undefined, + mlag_ibgp_origin_incomplete: bool | UndefinedType = Undefined, + mlag_interfaces: MlagInterfaces | UndefinedType = Undefined, + mlag_interfaces_speed: str | None | UndefinedType = Undefined, + mlag_peer_l3_vlan: int | UndefinedType = Undefined, + mlag_peer_l3_ipv4_pool: str | None | UndefinedType = Undefined, + mlag_peer_vlan: int | UndefinedType = Undefined, + mlag_peer_link_allowed_vlans: str | None | UndefinedType = Undefined, + mlag_peer_address_family: Literal["ipv4", "ipv6"] | UndefinedType = Undefined, + mlag_peer_ipv4_pool: str | None | UndefinedType = Undefined, + mlag_peer_ipv6_pool: str | None | UndefinedType = Undefined, + mlag_port_channel_id: int | None | UndefinedType = Undefined, + mlag_domain_id: str | None | UndefinedType = Undefined, + spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None | UndefinedType = Undefined, + spanning_tree_priority: int | UndefinedType = Undefined, + spanning_tree_root_super: bool | UndefinedType = Undefined, + virtual_router_mac_address: str | None | UndefinedType = Undefined, + inband_mgmt_interface: str | None | UndefinedType = Undefined, + inband_mgmt_vlan: int | UndefinedType = Undefined, + inband_mgmt_subnet: str | None | UndefinedType = Undefined, + inband_mgmt_ip: str | None | UndefinedType = Undefined, + inband_mgmt_gateway: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_address: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_subnet: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_gateway: str | None | UndefinedType = Undefined, + inband_mgmt_description: str | UndefinedType = Undefined, + inband_mgmt_vlan_name: str | UndefinedType = Undefined, + inband_mgmt_vrf: str | UndefinedType = Undefined, + inband_mgmt_mtu: int | UndefinedType = Undefined, + inband_ztp: bool | UndefinedType = Undefined, + inband_ztp_lacp_fallback_delay: int | UndefinedType = Undefined, + mpls_overlay_role: Literal["client", "server", "none"] | None | UndefinedType = Undefined, + overlay_address_families: OverlayAddressFamilies | UndefinedType = Undefined, + mpls_route_reflectors: MplsRouteReflectors | UndefinedType = Undefined, + bgp_cluster_id: str | None | UndefinedType = Undefined, + ptp: Ptp | UndefinedType = Undefined, + wan_role: Literal["client", "server"] | None | UndefinedType = Undefined, + cv_pathfinder_transit_mode: Literal["region", "zone"] | None | UndefinedType = Undefined, + cv_pathfinder_region: str | None | UndefinedType = Undefined, + cv_pathfinder_site: str | None | UndefinedType = Undefined, + wan_ha: WanHa | UndefinedType = Undefined, + dps_mss_ipv4: str | UndefinedType = Undefined, + l3_interfaces: L3Interfaces | UndefinedType = Undefined, + data_plane_cpu_allocation_max: int | None | UndefinedType = Undefined, + flow_tracker_type: Literal["sampled", "hardware"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Defaults. + + + Subclass of AvdModel. + + Args: + id: Unique identifier used for IP addressing and other algorithms. + platform: Arista platform family. + mac_address: Leverage to document management interface mac address. + system_mac_address: + System MAC Address in this following format: "xx:xx:xx:xx:xx:xx". + Set to the same MAC address as + available in "show version" on the device. + "system_mac_address" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + serial_number: + Set to the Serial Number of the device. + Only used for documentation purpose in the fabric + documentation and part of the structured_config. + "serial_number" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + rack: Rack that the switch is located in (only used in snmp_settings location). + mgmt_ip: Node management interface IPv4 address. + mgmt_gateway: + This key sets the management gateway for the device. It takes precedence over the global + `mgmt_gateway`. + ipv6_mgmt_ip: Node management interface IPv6 address. + ipv6_mgmt_gateway: + This key sets the ipv6 management gateway for the device. It takes precedence over the global + `ipv6_mgmt_gateway`. + mgmt_interface: + Management Interface Name. + Default -> platform_management_interface -> mgmt_interface -> + "Management1". + link_tracking: + This configures the Link Tracking Group on a switch as well as adds the p2p-uplinks of the switch as + the upstream interfaces. + Useful in EVPN multhoming designs. + + + Subclass of AvdModel. + lacp_port_id_range: + This will generate the "lacp port-id range", "begin" and "end" values based on node "id" and the + number of nodes in the "node_group". + Unique LACP port-id ranges are recommended for EVPN Multihoming + designs. + + + Subclass of AvdModel. + always_configure_ip_routing: + Force configuration of "ip routing" even on L2 devices. + Use this to retain behavior of AVD versions + below 4.0.0. + raw_eos_cli: EOS CLI rendered directly on the root level of the final EOS configuration. + structured_config: + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + uplink_type: + Override the default `uplink_type` set at the `node_type_key` level. + `uplink_type` must be "p2p" if + `vtep` or `underlay_router` is true for the `node_type_key` definition. + uplink_ipv4_pool: IPv4 subnet to use to connect to uplink switches. + uplink_interfaces: + Local uplink interfaces. + Each list item supports range syntax that can be expanded into a list of + interfaces. + If uplink_interfaces is not defined, platform-specific defaults (defined under + default_interfaces) will be used instead. + Please note that default_interfaces are not defined by + default, you should define these yourself. + + + Subclass of AvdList with `str` items. + uplink_switch_interfaces: + Interfaces located on uplink switches. + + Subclass of AvdList with `str` items. + uplink_switches: Subclass of AvdList with `str` items. + uplink_interface_speed: + Set point-to-Point interface speed and will apply to uplink interfaces on both ends. + (Uplink switch + interface speed can be overridden with `uplink_switch_interface_speed`). + Speed should be set in the + format `` or `forced ` or `auto `. + uplink_switch_interface_speed: + 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: Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting. + max_uplink_switches: + 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: + 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: Enable bfd on uplink interfaces. + uplink_native_vlan: + 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: + Enable PTP on all infrastructure links. + + Subclass of AvdModel. + uplink_macsec: + Enable MacSec on all uplinks. + + Subclass of AvdModel. + uplink_port_channel_id: + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink Port-channel + ID will be set to the number of the lowest member interface defined under `uplink_interfaces`. + For + example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ Eth11/1, Eth22/1 ] -> ID 111 + For + MLAG port-channels ID will be based on the lowest member interface on the first MLAG switch. + This + option overrides the default behavior and statically sets the local Port-channel ID. + Note! Make sure + the ID is unique and does not overlap with autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between 1 and 2000 and both MLAG switches must have the same + value. + uplink_switch_port_channel_id: + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink switch Port- + channel ID will be set to the number of the first interface defined under + `uplink_switch_interfaces`. + For example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ + Eth11/1, Eth22/1 ] -> ID 111 + For MLAG port-channels ID will be based on the lowest member interface + on the first MLAG switch. + This option overrides the default behavior and statically sets the Port- + channel ID on the uplink switch. + Note! Make sure the ID is unique and does not overlap with + autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between + 1 and 2000 and both MLAG switches must have the same value. + uplink_structured_config: + Custom structured config applied to "uplink_interfaces", and "uplink_switch_interfaces". + When + uplink_type == "p2p", custom structured config added under ethernet_interfaces.[name=] + for eos_cli_config_gen overrides the settings on the ethernet interface level. + When uplink_type == + "port-channel", custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen overrides the settings on the port-channel interface level. + "uplink_structured_config" is applied after "structured_config", so it can override + "structured_config" defined on node-level. + Note! The content of this dictionary is _not_ validated + by the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + mlag_port_channel_structured_config: + Custom structured config applied to MLAG peer link port-channel id. + Added under + port_channel_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the + port-channel interface level. + "mlag_port_channel_structured_config" is applied after + "structured_config", so it can override "structured_config" defined on node-level. + + + Subclass of + AvdModel. + mlag_peer_vlan_structured_config: + Custom structured config applied to MLAG Peer Link (control link) SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_vlan_structured_config" is applied after "structured_config", so it can + override "structured_config" defined on node-level. + + + Subclass of AvdModel. + mlag_peer_l3_vlan_structured_config: + Custom structured config applied to MLAG underlay L3 peering SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_l3_vlan_structured_config" is applied after "structured_config", so it + can override "structured_config" defined on node-level. + + + Subclass of AvdModel. + short_esi: + short_esi only valid for l2leaf devices using port-channel uplink. + Setting short_esi to "auto" + generates the short_esi automatically using a hash of configuration elements. + < 0000:0000:0000 | + auto >. + isis_system_id_prefix: (4.4 hexadecimal). + isis_maximum_paths: Number of path to configure in ECMP for ISIS. + is_type: Overrides `isis_default_is_type`. + node_sid_base: Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID. + loopback_ipv4_pool: IPv4 subnet for Loopback0 allocation. + loopback_ipv4_address: + IPv4 address without mask for Loopback0. + When set, it takes precedence over `loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not catch duplicates. + vtep_loopback_ipv4_pool: IPv4 subnet for VTEP-Loopback allocation. + vtep_loopback_ipv4_address: + IPv4 address without mask for VTEP-Loopback. + When set, it takes precedence over + `vtep_loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not + catch duplicates. + loopback_ipv4_offset: + Offset all assigned loopback IP addresses. + Required when the < loopback_ipv4_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid over-lapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv4_offset: < total # spine switches > or vice versa. + loopback_ipv6_pool: IPv6 subnet for Loopback0 allocation. + loopback_ipv6_offset: + Offset all assigned loopback IPv6 addresses. + Required when the < loopback_ipv6_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid overlapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv6_offset: < total # spine switches > or vice versa. + vtep: + Node is configured as a VTEP when applicable based on 'overlay_routing_protocol'. + Overrides VTEP + setting inherited from node_type_keys. + vtep_loopback: Set VXLAN source interface. + bgp_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + Required with eBGP. + bgp_defaults: + List of EOS commands to apply to BGP daemon. + + Subclass of AvdList with `str` items. + evpn_role: + Acting role in EVPN control plane. + Default is set in node_type definition from node_type_keys. + evpn_route_servers: + List of nodes acting as EVPN Route-Servers / Route-Reflectors. + + Subclass of AvdList with `str` + items. + evpn_services_l2_only: + Possibility to prevent configuration of Tenant VRFs and SVIs. + Override node definition + "network_services_l3" from node_type_keys. + This allows support for centralized routing. + filter: + Filter L3 and L2 network services based on tenant and tags (and operation filter). + If filter is not + defined it will default to all. + + + Subclass of AvdModel. + igmp_snooping_enabled: Activate or deactivate IGMP snooping on device level. + evpn_gateway: + Node is acting as EVPN Multi-Domain Gateway. + New BGP peer-group is generated between EVPN GWs in + different domains or between GWs and Route Servers. + Name can be changed under + "bgp_peer_groups.evpn_overlay_core" variable. + L3 rechability for different EVPN GWs must be already + in place, it is recommended to use DCI & L3 Edge if Route Servers and GWs are not defined under the + same Ansible inventory. + + + Subclass of AvdModel. + ipvpn_gateway: + Node is acting as IP-VPN Gateway for EVPN to MPLS-IP-VPN Interworking. The BGP peer group used for + this is "bgp_peer_groups.ipvpn_gateway_peers". + L3 Reachability is required for this to work, the + preferred method to establish underlay connectivity is to use core_interfaces. + + + Subclass of + AvdModel. + mlag: Enable / Disable auto MLAG, when two nodes are defined in node group. + mlag_dual_primary_detection: Enable / Disable MLAG dual primary detection. + mlag_ibgp_origin_incomplete: + Set origin of routes received from MLAG iBGP peer to incomplete. + The purpose is to optimize routing + for leaf loopbacks from spine perspective and + avoid suboptimal routing via peerlink for control + plane traffic. + mlag_interfaces: + Each list item supports range syntax that can be expanded into a list of interfaces. + Required when + MLAG leafs are present in the topology. + + + Subclass of AvdList with `str` items. + mlag_interfaces_speed: + Set MLAG interface speed. + Speed should be set in the format `` or `forced + ` or `auto `. + mlag_peer_l3_vlan: + Underlay L3 peering SVI interface id. + If set to 0 or the same vlan as mlag_peer_vlan, the + mlag_peer_vlan will be used for L3 peering. + mlag_peer_l3_ipv4_pool: + IP address pool used for MLAG underlay L3 peering. IP is derived from the node id. + Required when + MLAG leafs present in topology and they are using a separate L3 peering VLAN. + mlag_peer_vlan: MLAG Peer Link (control link) SVI interface id. + mlag_peer_link_allowed_vlans: mlag_peer_link_allowed_vlans + mlag_peer_address_family: + IP address family used to establish MLAG Peer Link (control link). + `ipv6` requires EOS version + 4.31.1F or higher. + Note: `ipv6` is not supported in combination with a common MLAG peer link VLAN + (ex. `mlag_peer_l3_vlan` set to 4094). + mlag_peer_ipv4_pool: + IPv4 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv4` (default). + mlag_peer_ipv6_pool: + IPv6 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv6`. + mlag_port_channel_id: + If not set, the mlag port-channel id is generated based on the digits of the first interface present + in 'mlag_interfaces'. + Valid port-channel id numbers are < 1-2000 > for EOS < 4.25.0F and < 1 - + 999999 > for EOS >= 4.25.0F. + mlag_domain_id: MLAG Domain ID. If not set the node group name (Set with "group" key) will be used. + spanning_tree_mode: spanning_tree_mode + spanning_tree_priority: + Spanning-tree priority configured for the selected mode. + For `rapid-pvst` the priority can also be + set per VLAN under network services. + spanning_tree_root_super: spanning_tree_root_super + virtual_router_mac_address: Virtual router mac address for anycast gateway. + inband_mgmt_interface: + Pointer to interface used for inband management. + All configuration must be done using other data + models like network services or structured_config. + 'inband_mgmt_interface' is only used to refer to + this interface as source in various management protocol settings (future feature). + + On L2 switches, + this defaults to Vlan if either 'inband_mgmt_subnet' or 'inband_mgmt_ip' is set. + inband_mgmt_vlan: + VLAN number used for inband management on L2 switches (switches using port-channel trunks as + uplinks). + When using 'inband_mgmt_subnet' the VLAN and SVIs will be created automatically on this + switch as well as all 'uplink_switches'. + When using 'inband_mgmt_ip' the VLAN and SVI will only be + created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be + created using network services data models. + inband_mgmt_subnet: + Optional IP subnet assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ip virtual-router" and host-route injection based on + ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + + 3 + + GW on l2leafs : + 1 + Assign range larger than total l2leafs + 5 + Setting is ignored if 'inband_mgmt_ip' is set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + inband_mgmt_ip: + IP address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_subnet', hence all behavior of 'inband_mgmt_subnet' is removed. + + If this is set the + VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN and SVI on + the parent switches must be created using network services data models. + + This setting is applicable + to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_gateway: + Default gateway configured in the 'inband_mgmt_vrf' when using 'inband_mgmt_ip'. Otherwise gateway + is derived from 'inband_mgmt_subnet' if set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + inband_mgmt_ipv6_address: + IPv6 address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_ipv6_subnet', hence the configuration of 'inband_mgmt_ipv6_subnet' is ignored. + + If this + is set the VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN + and SVI on the parent switches must be created using network services data models. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_ipv6_subnet: + Optional IPv6 prefix assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ipv6 virtual-router" and host-route injection based + on ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN + extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + 3 + + GW on l2leafs : + 1 + Assign range larger than + total l2leafs + 5 + + Setting is ignored if 'inband_mgmt_ipv6_address' is set. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_ipv6_gateway: + Default gateway configured in the 'inband_mgmt_vrf'. + Used when `inband_mgmt_ipv6_address` is set. + Ignored when 'inband_mgmt_ipv6_subnet' is set (first IP in subnet used as gateway). + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_description: + Description configured on the Inband Management SVI. + + This setting is only applied on the devices + where it is set, it does not automatically affect any parent/child devices configuration, so it must + be set on each applicable node/node-group/node-type as needed. + inband_mgmt_vlan_name: + Name configured on the Inband Management VLAN. + This setting is only applied on the devices where it + is set, it does not automatically affect any parent/child devices configuration, so it must be set + on each applicable node/node-group/node-type as needed. + inband_mgmt_vrf: + VRF configured on the Inband Management Interface. + The VRF is created if not already created by + other means. + This setting is only applied on the devices where it is set, it does not automatically + affect any parent/child devices configuration, so it must be set on each applicable node/node- + group/node-type as needed. + inband_mgmt_mtu: + MTU configured on the Inband Management Interface. + This setting is only applied on the devices where + it is set, it does not automatically affect any parent/child devices configuration, so it must be + set on each applicable node/node-group/node-type as needed. + inband_ztp: + Enable to configure upstream device with proper configuration to allow downstream devices to be + Zero-Touch-Provisioned over the uplink interfaces. + For L2 devices this setting also requires that + the `inband_mgmt_vlan` is set for the node. + + PREVIEW: Support for L3 devices is marked as "preview", + meaning the data models or generated configuration can change at any time. + inband_ztp_lacp_fallback_delay: + Set the LACP fallback timeout of the upstream device's port-channel towards the downstream inband + ZTP node. + This setting also requires that `inband_ztp` is set for the node. + mpls_overlay_role: + Set the default mpls overlay role. + Acting role in overlay control plane. + overlay_address_families: + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + mpls_route_reflectors: + List of inventory hostname acting as MPLS route-reflectors. + + Subclass of AvdList with `str` items. + bgp_cluster_id: Set BGP cluster id. + ptp: Subclass of AvdModel. + wan_role: + Override the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + cv_pathfinder_transit_mode: + Configure the transit mode for a WAN client for CV Pathfinder designs + only when the `wan_mode` root + key is set to `cv_pathfinder`. + + 'zone' is currently not supported. + cv_pathfinder_region: + The CV Pathfinder region name. + This key is required for WAN routers but optional for pathfinders. + The region name must be defined under 'cv_pathfinder_regions'. + cv_pathfinder_site: + The CV Pathfinder site name. + This key is required for WAN routers but optional for pathfinders. + For + WAN routers and pathfinders with `cv_pathfinder_region`, the site name must be defined for the + relevant region under 'cv_pathfinder_regions'. + For pathfinders without `cv_pathfinder_region` set, + the site must be defined under `cv_pathfinder_global_sites`. + wan_ha: + PREVIEW: This key is currently not supported + + The key is supported only if `wan_mode` == `cv- + pathfinder`. + AutoVPN support is still to be determined. + + Maximum 2 devices supported by group for + HA. + + Subclass of AvdModel. + dps_mss_ipv4: IPv4 MSS value configured under "router path-selection" on WAN Devices. + l3_interfaces: + L3 Interfaces to configure on the node. + Used to define the node for WAN interfaces when + `wan_carrier` is set. + + Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is + `name` (`str`). + data_plane_cpu_allocation_max: + Set the maximum number of CPU used for the data plane. + This setting is useful on virtual Route + Reflectors and Pathfinders where more CPU cores should be allocated for control plane. + flow_tracker_type: + Set the flow tracker type. + Override the `default_flow_tracker_type`` set at the `node_type_key` + level. + `default_flow_tracker_type` default value is `sampled`. + _custom_data: _custom_data + + """ + + class NodeGroupsItem(AvdModel): + """Subclass of AvdModel.""" + + class NodesItem(AvdModel): + """Subclass of AvdModel.""" + + class DownlinkPoolsItem(AvdModel): + """Subclass of AvdModel.""" + + class DownlinkInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DownlinkInterfaces._item_type = str + + _fields: ClassVar[dict] = { + "ipv4_pool": {"type": str}, + "downlink_interfaces": {"type": DownlinkInterfaces}, + "_custom_data": {"type": dict}, + } + ipv4_pool: str | None + """IPv4 pool from which subnets will be allocated for links to downlink switches.""" + downlink_interfaces: DownlinkInterfaces + """ + List of downlink interfaces or ranges of interfaces to use this pool. The index of the interface in + this list will determine which subnet will be taken from the pool. + + Subclass of AvdList with `str` + items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4_pool: str | None | UndefinedType = Undefined, + downlink_interfaces: DownlinkInterfaces | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DownlinkPoolsItem. + + + Subclass of AvdModel. + + Args: + ipv4_pool: IPv4 pool from which subnets will be allocated for links to downlink switches. + downlink_interfaces: + List of downlink interfaces or ranges of interfaces to use this pool. The index of the interface in + this list will determine which subnet will be taken from the pool. + + Subclass of AvdList with `str` + items. + _custom_data: _custom_data + + """ + + class DownlinkPools(AvdList[DownlinkPoolsItem]): + """Subclass of AvdList with `DownlinkPoolsItem` items.""" + + DownlinkPools._item_type = DownlinkPoolsItem + + class LinkTracking(AvdModel): + """Subclass of AvdModel.""" + + class GroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "recovery_delay": {"type": int}, + "links_minimum": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str | None + """Tracking group name.""" + recovery_delay: int | None + """default -> platform_settings_mlag_reload_delay -> 300.""" + links_minimum: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + recovery_delay: int | None | UndefinedType = Undefined, + links_minimum: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GroupsItem. + + + Subclass of AvdModel. + + Args: + name: Tracking group name. + recovery_delay: default -> platform_settings_mlag_reload_delay -> 300. + links_minimum: links_minimum + _custom_data: _custom_data + + """ + + class Groups(AvdList[GroupsItem]): + """Subclass of AvdList with `GroupsItem` items.""" + + Groups._item_type = GroupsItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "groups": {"type": Groups, "default": lambda cls: coerce_type([{"name": "LT_GROUP1"}], target_type=cls)}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + groups: Groups + """ + Link Tracking Groups. + By default a single group named "LT_GROUP1" is defined with default values. + Any groups defined under "groups" will replace the default. + + + Subclass of AvdList with `GroupsItem` + items. + + Default value: `lambda cls: coerce_type([{"name": "LT_GROUP1"}], target_type=cls)` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + groups: + Link Tracking Groups. + By default a single group named "LT_GROUP1" is defined with default values. + Any groups defined under "groups" will replace the default. + + + Subclass of AvdList with `GroupsItem` + items. + _custom_data: _custom_data + + """ + + class LacpPortIdRange(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "size": {"type": int, "default": 128}, + "offset": {"type": int, "default": 0}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + size: int + """ + Recommended size > = number of ports in the switch. + + Default value: `128` + """ + offset: int + """ + Offset is used to avoid overlapping port-id ranges of different switches. + Useful when a "connected- + endpoint" is connected to switches in different "node_groups". + + Default value: `0` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + size: int | UndefinedType = Undefined, + offset: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LacpPortIdRange. + + + Subclass of AvdModel. + + Args: + enabled: enabled + size: Recommended size > = number of ports in the switch. + offset: + Offset is used to avoid overlapping port-id ranges of different switches. + Useful when a "connected- + endpoint" is connected to switches in different "node_groups". + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen): + """Subclass of AvdModel.""" + + class UplinkInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkInterfaces._item_type = str + + class UplinkSwitchInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkSwitchInterfaces._item_type = str + + class UplinkSwitches(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkSwitches._item_type = str + + class UplinkPtp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enable": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enable: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, enable: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + UplinkPtp. + + + Subclass of AvdModel. + + Args: + enable: enable + _custom_data: _custom_data + + """ + + class UplinkMacsec(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "_custom_data": {"type": dict}} + profile: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, profile: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + UplinkMacsec. + + + Subclass of AvdModel. + + Args: + profile: profile + _custom_data: _custom_data + + """ + + class MlagPortChannelStructuredConfig(EosCliConfigGen.PortChannelInterfacesItem): + """Subclass of AvdModel.""" + + class MlagPeerVlanStructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + class MlagPeerL3VlanStructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + class BgpDefaults(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + BgpDefaults._item_type = str + + class EvpnRouteServers(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + EvpnRouteServers._item_type = str + + class Filter(AvdModel): + """Subclass of AvdModel.""" + + class Tenants(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tenants._item_type = str + + class Tags(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tags._item_type = str + + class AllowVrfs(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AllowVrfs._item_type = str + + class DenyVrfs(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DenyVrfs._item_type = str + + class AlwaysIncludeVrfsInTenants(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AlwaysIncludeVrfsInTenants._item_type = str + + _fields: ClassVar[dict] = { + "tenants": {"type": Tenants, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "tags": {"type": Tags, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "allow_vrfs": {"type": AllowVrfs, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "deny_vrfs": {"type": DenyVrfs, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "always_include_vrfs_in_tenants": {"type": AlwaysIncludeVrfsInTenants}, + "only_vlans_in_use": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + tenants: Tenants + """ + Limit configured Network Services to those defined under these Tenants. Set to ['all'] for all + Tenants (default). + This list also limits Tenants included by `always_include_vrfs_in_tenants`. + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + tags: Tags + """ + Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default). + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + allow_vrfs: AllowVrfs + """ + Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs + (default). + This list also limits VRFs included by `always_include_vrfs_in_tenants`. + + Subclass of + AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + deny_vrfs: DenyVrfs + """ + Prevent configuration of Network Services defined under these VRFs. + This list prevents the given + VRFs to be included by any other filtering mechanism. + + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + always_include_vrfs_in_tenants: AlwaysIncludeVrfsInTenants + """ + List of tenants where VRFs will be configured even if VLANs are not included in tags. + Useful for L3 + "border" leaf. + + + Subclass of AvdList with `str` items. + """ + only_vlans_in_use: bool + """ + Only configure VLANs, SVIs, VRFs in use by connected endpoints or downstream L2 switches. + Note! This + feature only considers configuration managed by eos_designs. + This excludes structured_config, + custom_structured_configuration_, raw_eos_cli, eos_cli, custom templates, configlets etc. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + tenants: Tenants | UndefinedType = Undefined, + tags: Tags | UndefinedType = Undefined, + allow_vrfs: AllowVrfs | UndefinedType = Undefined, + deny_vrfs: DenyVrfs | UndefinedType = Undefined, + always_include_vrfs_in_tenants: AlwaysIncludeVrfsInTenants | UndefinedType = Undefined, + only_vlans_in_use: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Filter. + + + Subclass of AvdModel. + + Args: + tenants: + Limit configured Network Services to those defined under these Tenants. Set to ['all'] for all + Tenants (default). + This list also limits Tenants included by `always_include_vrfs_in_tenants`. + Subclass of AvdList with `str` items. + tags: + Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default). + Subclass of AvdList with `str` items. + allow_vrfs: + Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs + (default). + This list also limits VRFs included by `always_include_vrfs_in_tenants`. + + Subclass of + AvdList with `str` items. + deny_vrfs: + Prevent configuration of Network Services defined under these VRFs. + This list prevents the given + VRFs to be included by any other filtering mechanism. + + Subclass of AvdList with `str` items. + always_include_vrfs_in_tenants: + List of tenants where VRFs will be configured even if VLANs are not included in tags. + Useful for L3 + "border" leaf. + + + Subclass of AvdList with `str` items. + only_vlans_in_use: + Only configure VLANs, SVIs, VRFs in use by connected endpoints or downstream L2 switches. + Note! This + feature only considers configuration managed by eos_designs. + This excludes structured_config, + custom_structured_configuration_, raw_eos_cli, eos_cli, custom templates, configlets etc. + _custom_data: _custom_data + + """ + + class EvpnGateway(AvdModel): + """Subclass of AvdModel.""" + + class RemotePeersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hostname": {"type": str}, + "ip_address": {"type": str}, + "bgp_as": {"type": str}, + "_custom_data": {"type": dict}, + } + hostname: str + """Hostname of remote EVPN GW server.""" + ip_address: str | None + """Peering IP of remote Route Server.""" + bgp_as: str | None + """ + Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being + interpreted as a float number. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: str | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + bgp_as: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemotePeersItem. + + + Subclass of AvdModel. + + Args: + hostname: Hostname of remote EVPN GW server. + ip_address: Peering IP of remote Route Server. + bgp_as: + Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being + interpreted as a float number. + _custom_data: _custom_data + + """ + + class RemotePeers(AvdIndexedList[str, RemotePeersItem]): + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + + _primary_key: ClassVar[str] = "hostname" + + RemotePeers._item_type = RemotePeersItem + + class EvpnL2(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enabled: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, enabled: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + EvpnL2. + + + Subclass of AvdModel. + + Args: + enabled: enabled + _custom_data: _custom_data + + """ + + class EvpnL3(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "inter_domain": {"type": bool, "default": True}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + inter_domain: bool + """Default value: `True`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + inter_domain: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnL3. + + + Subclass of AvdModel. + + Args: + enabled: enabled + inter_domain: inter_domain + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "remote_peers": {"type": RemotePeers}, + "evpn_l2": {"type": EvpnL2}, + "evpn_l3": {"type": EvpnL3}, + "_custom_data": {"type": dict}, + } + remote_peers: RemotePeers + """ + Define remote peers of the EVPN VXLAN Gateway. + If the hostname can be found in the inventory, + ip_address and BGP ASN will be automatically populated. Manual override takes precedence. + If the + peer's hostname can not be found in the inventory, ip_address and bgp_as must be defined. + + + Subclass + of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + """ + evpn_l2: EvpnL2 + """ + Enable EVPN Gateway functionality for route-types 2 (MAC-IP) and 3 (IMET). + + Subclass of AvdModel. + """ + evpn_l3: EvpnL3 + """ + Enable EVPN Gateway functionality for route-type 5 (IP-PREFIX). + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + remote_peers: RemotePeers | UndefinedType = Undefined, + evpn_l2: EvpnL2 | UndefinedType = Undefined, + evpn_l3: EvpnL3 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnGateway. + + + Subclass of AvdModel. + + Args: + remote_peers: + Define remote peers of the EVPN VXLAN Gateway. + If the hostname can be found in the inventory, + ip_address and BGP ASN will be automatically populated. Manual override takes precedence. + If the + peer's hostname can not be found in the inventory, ip_address and bgp_as must be defined. + + + Subclass + of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + evpn_l2: + Enable EVPN Gateway functionality for route-types 2 (MAC-IP) and 3 (IMET). + + Subclass of AvdModel. + evpn_l3: + Enable EVPN Gateway functionality for route-type 5 (IP-PREFIX). + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class IpvpnGateway(AvdModel): + """Subclass of AvdModel.""" + + class AddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AddressFamilies._item_type = str + + class RemotePeersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hostname": {"type": str}, + "ip_address": {"type": str}, + "bgp_as": {"type": str}, + "_custom_data": {"type": dict}, + } + hostname: str + """Hostname of remote IPVPN Peer.""" + ip_address: str + """Peering IP of remote IPVPN Peer.""" + bgp_as: str + """ + Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For + asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted + as a float number. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: str | UndefinedType = Undefined, + ip_address: str | UndefinedType = Undefined, + bgp_as: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemotePeersItem. + + + Subclass of AvdModel. + + Args: + hostname: Hostname of remote IPVPN Peer. + ip_address: Peering IP of remote IPVPN Peer. + bgp_as: + Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For + asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted + as a float number. + _custom_data: _custom_data + + """ + + class RemotePeers(AvdIndexedList[str, RemotePeersItem]): + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + + _primary_key: ClassVar[str] = "hostname" + + RemotePeers._item_type = RemotePeersItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "evpn_domain_id": {"type": str, "default": "65535:1"}, + "ipvpn_domain_id": {"type": str, "default": "65535:2"}, + "enable_d_path": {"type": bool, "default": True}, + "maximum_routes": {"type": int, "default": 0}, + "local_as": {"type": str}, + "address_families": {"type": AddressFamilies, "default": lambda cls: coerce_type(["vpn-ipv4"], target_type=cls)}, + "remote_peers": {"type": RemotePeers}, + "_custom_data": {"type": dict}, + } + enabled: bool + evpn_domain_id: str + """ + Domain ID to assign to EVPN address family for use with D-path. Format :. + + Default value: `"65535:1"` + """ + ipvpn_domain_id: str + """ + Domain ID to assign to IPVPN address families for use with D-path. Format :. + + Default value: `"65535:2"` + """ + enable_d_path: bool + """ + Enable D-path for use with BGP bestpath selection algorithm. + + Default value: `True` + """ + maximum_routes: int + """ + Maximum routes to accept from IPVPN remote peers. + + Default value: `0` + """ + local_as: str | None + """ + Local BGP AS applied to peering with IPVPN remote peers. + BGP AS <1-4294967295> or AS number in asdot + notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number. + """ + address_families: AddressFamilies + """ + IPVPN address families to enable for remote peers. + + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["vpn-ipv4"], target_type=cls)` + """ + remote_peers: RemotePeers + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + evpn_domain_id: str | UndefinedType = Undefined, + ipvpn_domain_id: str | UndefinedType = Undefined, + enable_d_path: bool | UndefinedType = Undefined, + maximum_routes: int | UndefinedType = Undefined, + local_as: str | None | UndefinedType = Undefined, + address_families: AddressFamilies | UndefinedType = Undefined, + remote_peers: RemotePeers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpvpnGateway. + + + Subclass of AvdModel. + + Args: + enabled: enabled + evpn_domain_id: Domain ID to assign to EVPN address family for use with D-path. Format :. + ipvpn_domain_id: Domain ID to assign to IPVPN address families for use with D-path. Format :. + enable_d_path: Enable D-path for use with BGP bestpath selection algorithm. + maximum_routes: Maximum routes to accept from IPVPN remote peers. + local_as: + Local BGP AS applied to peering with IPVPN remote peers. + BGP AS <1-4294967295> or AS number in asdot + notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number. + address_families: + IPVPN address families to enable for remote peers. + + Subclass of AvdList with `str` items. + remote_peers: Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + _custom_data: _custom_data + + """ + + class MlagInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MlagInterfaces._item_type = str + + class OverlayAddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + OverlayAddressFamilies._item_type = str + + class MplsRouteReflectors(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MplsRouteReflectors._item_type = str + + class Ptp(AvdModel): + """Subclass of AvdModel.""" + + class Dscp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"general_messages": {"type": int}, "event_messages": {"type": int}, "_custom_data": {"type": dict}} + general_messages: int | None + event_messages: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + general_messages: int | None | UndefinedType = Undefined, + event_messages: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dscp. + + + Subclass of AvdModel. + + Args: + general_messages: general_messages + event_messages: event_messages + _custom_data: _custom_data + + """ + + class Monitor(AvdModel): + """Subclass of AvdModel.""" + + class Threshold(AvdModel): + """Subclass of AvdModel.""" + + class Drop(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "offset_from_master": {"type": int}, + "mean_path_delay": {"type": int}, + "_custom_data": {"type": dict}, + } + offset_from_master: int | None + mean_path_delay: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + offset_from_master: int | None | UndefinedType = Undefined, + mean_path_delay: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Drop. + + + Subclass of AvdModel. + + Args: + offset_from_master: offset_from_master + mean_path_delay: mean_path_delay + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "offset_from_master": {"type": int, "default": 250}, + "mean_path_delay": {"type": int, "default": 1500}, + "drop": {"type": Drop}, + "_custom_data": {"type": dict}, + } + offset_from_master: int + """Default value: `250`""" + mean_path_delay: int + """Default value: `1500`""" + drop: Drop + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + offset_from_master: int | UndefinedType = Undefined, + mean_path_delay: int | UndefinedType = Undefined, + drop: Drop | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Threshold. + + + Subclass of AvdModel. + + Args: + offset_from_master: offset_from_master + mean_path_delay: mean_path_delay + drop: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MissingMessage(AvdModel): + """Subclass of AvdModel.""" + + class Intervals(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "announce": {"type": int}, + "follow_up": {"type": int}, + "sync": {"type": int}, + "_custom_data": {"type": dict}, + } + announce: int | None + follow_up: int | None + sync: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + announce: int | None | UndefinedType = Undefined, + follow_up: int | None | UndefinedType = Undefined, + sync: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Intervals. + + + Subclass of AvdModel. + + Args: + announce: announce + follow_up: follow_up + sync: sync + _custom_data: _custom_data + + """ + + class SequenceIds(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "announce": {"type": int, "default": 3}, + "delay_resp": {"type": int, "default": 3}, + "follow_up": {"type": int, "default": 3}, + "sync": {"type": int, "default": 3}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + announce: int + """Default value: `3`""" + delay_resp: int + """Default value: `3`""" + follow_up: int + """Default value: `3`""" + sync: int + """Default value: `3`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + announce: int | UndefinedType = Undefined, + delay_resp: int | UndefinedType = Undefined, + follow_up: int | UndefinedType = Undefined, + sync: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceIds. + + + Subclass of AvdModel. + + Args: + enabled: enabled + announce: announce + delay_resp: delay_resp + follow_up: follow_up + sync: sync + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "intervals": {"type": Intervals}, + "sequence_ids": {"type": SequenceIds}, + "_custom_data": {"type": dict}, + } + intervals: Intervals + """Subclass of AvdModel.""" + sequence_ids: SequenceIds + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + intervals: Intervals | UndefinedType = Undefined, + sequence_ids: SequenceIds | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingMessage. + + + Subclass of AvdModel. + + Args: + intervals: Subclass of AvdModel. + sequence_ids: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "threshold": {"type": Threshold}, + "missing_message": {"type": MissingMessage}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + threshold: Threshold + """Subclass of AvdModel.""" + missing_message: MissingMessage + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + threshold: Threshold | UndefinedType = Undefined, + missing_message: MissingMessage | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Monitor. + + + Subclass of AvdModel. + + Args: + enabled: enabled + threshold: Subclass of AvdModel. + missing_message: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "profile": {"type": str}, + "mlag": {"type": bool, "default": False}, + "domain": {"type": int, "default": 127}, + "priority1": {"type": int}, + "priority2": {"type": int}, + "auto_clock_identity": {"type": bool}, + "clock_identity_prefix": {"type": str, "default": "00:1C:73"}, + "clock_identity": {"type": str}, + "source_ip": {"type": str}, + "mode": {"type": str, "default": "boundary"}, + "mode_one_step": {"type": bool, "default": False}, + "ttl": {"type": int}, + "forward_unicast": {"type": bool, "default": False}, + "dscp": {"type": Dscp}, + "monitor": {"type": Monitor}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + profile: str | None + """ + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + """ + mlag: bool + """ + Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be + configured on the MLAG peer-link port-channel. + + Default value: `False` + """ + domain: int + """Default value: `127`""" + priority1: int | None + """default -> automatically set based on node_type.""" + priority2: int | None + """default -> (node_id modulus 256).""" + auto_clock_identity: bool | None + """ + If you prefer to have PTP clock identity be the system MAC-address of the switch, which is the + default EOS behaviour, simply disable the automatic PTP clock identity. + default -> + (clock_identity_prefix = 00:1C:73 (default)) + (PTP priority 1 as HEX) + ":00:" + (PTP priority 2 as + HEX). + """ + clock_identity_prefix: str + """ + PTP clock idetentiy 3-byte prefix. i.e. "01:02:03". + By default the 3-byte prefix is "00:1C:73". + This + can be overridden if auto_clock_identity is set to true (which is the default). + + Default value: `"00:1C:73"` + """ + clock_identity: str | None + """Set PTP clock identity manually. 6-byte value i.e. "01:02:03:04:05:06".""" + source_ip: str | None + """ + By default in EOS, PTP packets are sourced with an IP address from the routed port or from the + relevant SVI, which is the recommended behaviour. + This can be set manually if required, for example, + to a value of "10.1.2.3". + """ + mode: Literal["boundary"] + """Default value: `"boundary"`""" + mode_one_step: bool + """Default value: `False`""" + ttl: int | None + forward_unicast: bool + """ + Enable PTP unicast forwarding. + + Default value: `False` + """ + dscp: Dscp + """Subclass of AvdModel.""" + monitor: Monitor + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + profile: str | None | UndefinedType = Undefined, + mlag: bool | UndefinedType = Undefined, + domain: int | UndefinedType = Undefined, + priority1: int | None | UndefinedType = Undefined, + priority2: int | None | UndefinedType = Undefined, + auto_clock_identity: bool | None | UndefinedType = Undefined, + clock_identity_prefix: str | UndefinedType = Undefined, + clock_identity: str | None | UndefinedType = Undefined, + source_ip: str | None | UndefinedType = Undefined, + mode: Literal["boundary"] | UndefinedType = Undefined, + mode_one_step: bool | UndefinedType = Undefined, + ttl: int | None | UndefinedType = Undefined, + forward_unicast: bool | UndefinedType = Undefined, + dscp: Dscp | UndefinedType = Undefined, + monitor: Monitor | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ptp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + profile: + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + mlag: + Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be + configured on the MLAG peer-link port-channel. + domain: domain + priority1: default -> automatically set based on node_type. + priority2: default -> (node_id modulus 256). + auto_clock_identity: + If you prefer to have PTP clock identity be the system MAC-address of the switch, which is the + default EOS behaviour, simply disable the automatic PTP clock identity. + default -> + (clock_identity_prefix = 00:1C:73 (default)) + (PTP priority 1 as HEX) + ":00:" + (PTP priority 2 as + HEX). + clock_identity_prefix: + PTP clock idetentiy 3-byte prefix. i.e. "01:02:03". + By default the 3-byte prefix is "00:1C:73". + This + can be overridden if auto_clock_identity is set to true (which is the default). + clock_identity: Set PTP clock identity manually. 6-byte value i.e. "01:02:03:04:05:06". + source_ip: + By default in EOS, PTP packets are sourced with an IP address from the routed port or from the + relevant SVI, which is the recommended behaviour. + This can be set manually if required, for example, + to a value of "10.1.2.3". + mode: mode + mode_one_step: mode_one_step + ttl: ttl + forward_unicast: Enable PTP unicast forwarding. + dscp: Subclass of AvdModel. + monitor: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class WanHa(AvdModel): + """Subclass of AvdModel.""" + + class HaInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + HaInterfaces._item_type = str + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "ipsec": {"type": bool, "default": True}, + "mtu": {"type": int, "default": 9194}, + "ha_interfaces": {"type": HaInterfaces}, + "ha_ipv4_pool": {"type": str}, + "max_ha_interfaces": {"type": int}, + "port_channel_id": {"type": int}, + "use_port_channel_for_direct_ha": {"type": bool, "default": True}, + "flow_tracking": {"type": FlowTracking}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group.""" + ipsec: bool + """ + Enable / Disable IPsec over HA path-group when HA is enabled. + + Default value: `True` + """ + mtu: int + """ + Set MTU on WAN HA interfaces. + + Default value: `9194` + """ + ha_interfaces: HaInterfaces + """ + Local WAN HA interfaces + Overwrite the default behavior which is to pick all the `uplink_interfaces`. + Can be used to filter uplink interfaces when there are multiple uplinks. + Limitations: + Either all + interfaces must be uplinks or all interfaces must not be uplinks. + Only one interface is supported + for non uplinks. + + Subclass of AvdList with `str` items. + """ + ha_ipv4_pool: str | None + """ + IP address pool used for WAN HA connectivity. + IP is derived from the node ID. + Not used for uplink + interfaces. + """ + max_ha_interfaces: int | None + """ + Number of parallel links towards HA switches. + Can be used to reserve IP addresses for future + parallel HA links. + """ + port_channel_id: int | None + """Port-channel ID to use for direct HA.""" + use_port_channel_for_direct_ha: bool + """ + Enable or disable using a port-channel interface for direct HA when there is only one interface. + This feature was introduced in EOS 4.33.0F. + + Default value: `True` + """ + flow_tracking: FlowTracking + """ + Configures flow-tracking on the HA interfaces. Overrides `fabric_flow_tracking.wan_ha_links` + setting. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + ipsec: bool | UndefinedType = Undefined, + mtu: int | UndefinedType = Undefined, + ha_interfaces: HaInterfaces | UndefinedType = Undefined, + ha_ipv4_pool: str | None | UndefinedType = Undefined, + max_ha_interfaces: int | None | UndefinedType = Undefined, + port_channel_id: int | None | UndefinedType = Undefined, + use_port_channel_for_direct_ha: bool | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + WanHa. + + + Subclass of AvdModel. + + Args: + enabled: Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group. + ipsec: Enable / Disable IPsec over HA path-group when HA is enabled. + mtu: Set MTU on WAN HA interfaces. + ha_interfaces: + Local WAN HA interfaces + Overwrite the default behavior which is to pick all the `uplink_interfaces`. + Can be used to filter uplink interfaces when there are multiple uplinks. + Limitations: + Either all + interfaces must be uplinks or all interfaces must not be uplinks. + Only one interface is supported + for non uplinks. + + Subclass of AvdList with `str` items. + ha_ipv4_pool: + IP address pool used for WAN HA connectivity. + IP is derived from the node ID. + Not used for uplink + interfaces. + max_ha_interfaces: + Number of parallel links towards HA switches. + Can be used to reserve IP addresses for future + parallel HA links. + port_channel_id: Port-channel ID to use for direct HA. + use_port_channel_for_direct_ha: + Enable or disable using a port-channel interface for direct HA when there is only one interface. + This feature was introduced in EOS 4.33.0F. + flow_tracking: + Configures flow-tracking on the HA interfaces. Overrides `fabric_flow_tracking.wan_ha_links` + setting. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L3InterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "peer_as": {"type": str}, + "ipv4_prefix_list_in": {"type": str}, + "ipv4_prefix_list_out": {"type": str}, + "_custom_data": {"type": dict}, + } + peer_as: str + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + ipv4_prefix_list_in: str | None + """ + Prefix List Name. Accept routes for only these prefixes from the peer. + Required for wan interfaces. + """ + ipv4_prefix_list_out: str | None + """ + Prefix List Name. Advertise routes for only these prefixes. + If not specified, nothing would be + advertised. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + peer_as: str | UndefinedType = Undefined, + ipv4_prefix_list_in: str | None | UndefinedType = Undefined, + ipv4_prefix_list_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + peer_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + ipv4_prefix_list_in: + Prefix List Name. Accept routes for only these prefixes from the peer. + Required for wan interfaces. + ipv4_prefix_list_out: + Prefix List Name. Advertise routes for only these prefixes. + If not specified, nothing would be + advertised. + _custom_data: _custom_data + + """ + + class StaticRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "_custom_data": {"type": dict}} + prefix: str + """IPv4_network/Mask.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, prefix: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + StaticRoutesItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv4_network/Mask. + _custom_data: _custom_data + + """ + + class StaticRoutes(AvdList[StaticRoutesItem]): + """Subclass of AvdList with `StaticRoutesItem` items.""" + + StaticRoutes._item_type = StaticRoutesItem + + class CvPathfinderInternetExit(AvdModel): + """Subclass of AvdModel.""" + + class PoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "tunnel_interface_numbers": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Internet-exit policy name.""" + tunnel_interface_numbers: str | None + """ + Number range to use for Tunnel interfaces to an internet-exit service provider using this local + interface. + Examples: '1-3' or '100,200,300' + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + tunnel_interface_numbers: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PoliciesItem. + + + Subclass of AvdModel. + + Args: + name: Internet-exit policy name. + tunnel_interface_numbers: + Number range to use for Tunnel interfaces to an internet-exit service provider using this local + interface. + Examples: '1-3' or '100,200,300' + _custom_data: _custom_data + + """ + + class Policies(AvdIndexedList[str, PoliciesItem]): + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Policies._item_type = PoliciesItem + + _fields: ClassVar[dict] = {"policies": {"type": Policies}, "_custom_data": {"type": dict}} + policies: Policies + """ + List of Internet-exit policies using this interface as exit. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, policies: Policies | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + CvPathfinderInternetExit. + + + Subclass of AvdModel. + + Args: + policies: + List of Internet-exit policies using this interface as exit. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "profile": {"type": str}, + "name": {"type": str}, + "description": {"type": str}, + "ip_address": {"type": str}, + "dhcp_ip": {"type": str}, + "public_ip": {"type": str}, + "encapsulation_dot1q_vlan": {"type": int}, + "dhcp_accept_default_route": {"type": bool, "default": True}, + "enabled": {"type": bool, "default": True}, + "speed": {"type": str}, + "peer": {"type": str}, + "peer_interface": {"type": str}, + "peer_ip": {"type": str}, + "bgp": {"type": Bgp}, + "ipv4_acl_in": {"type": str}, + "ipv4_acl_out": {"type": str}, + "static_routes": {"type": StaticRoutes}, + "qos_profile": {"type": str}, + "wan_carrier": {"type": str}, + "wan_circuit_id": {"type": str}, + "connected_to_pathfinder": {"type": bool, "default": True}, + "cv_pathfinder_internet_exit": {"type": CvPathfinderInternetExit}, + "raw_eos_cli": {"type": str}, + "flow_tracking": {"type": FlowTracking}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + profile: str | None + """L3 interface profile name. Profile defined under `l3_interface_profiles`.""" + name: str + """ + Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. + For a + subinterface, the parent physical interface is automatically created. + """ + description: str | None + """ + Interface description. + If not set a default description will be configured with '[[ + ]]'. + """ + ip_address: str | None + """Node IPv4 address/Mask or 'dhcp'.""" + dhcp_ip: str | None + """ + When the `ip_address` is `dhcp`, this optional field allows to indicate the expected + IPv4 address + (without mask) to be allocated on the interface if known. + This is not rendered in the configuration + but can be used for substitution of 'interface_ip' in the Access-list + set under `ipv4_acl_in` and + `ipv4_acl_out`. + """ + public_ip: str | None + """ + Node IPv4 address (no mask). + + This is used to get the public IP (if known) when the device is behind + NAT. + This is only used for `wan_rr` routers (AutoVPN RRs and Pathfinders) to determine the Public IP + with the following preference: + `wan_route_servers.path_groups.interfaces.ip_address` + -> + `l3_interfaces.public_ip` + -> `l3_interfaces.ip_address` + + The determined Public IP is used + by WAN routers when peering with this interface. + """ + encapsulation_dot1q_vlan: int | None + """ + For subinterfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + """ + dhcp_accept_default_route: bool + """ + Accept a default route from DHCP if `ip_address` is set to `dhcp`. + + Default value: `True` + """ + enabled: bool + """ + Enable or Shutdown the interface. + + Default value: `True` + """ + speed: str | None + """ + Speed should be set in the format `` or `forced ` or `auto + `. + """ + peer: str | None + """The peer device name. Used for description and documentation.""" + peer_interface: str | None + """The peer device interface. Used for description and documentation.""" + peer_ip: str | None + """ + The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true + and `ip` is an IP address. + """ + bgp: Bgp + """ + Enforce IPv4 BGP peering for the peer + + Subclass of AvdModel. + """ + ipv4_acl_in: str | None + """ + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + Required + for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under + `wan_carriers`. + """ + ipv4_acl_out: str | None + """ + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + """ + static_routes: StaticRoutes + """ + Configure IPv4 static routes pointing to `peer_ip`. + + Subclass of AvdList with `StaticRoutesItem` + items. + """ + qos_profile: str | None + """QOS service profile.""" + wan_carrier: str | None + """ + The WAN carrier this interface is connected to. + This is used to infer the path-groups in which this + interface should be configured. + Unless the carrier is marked as 'trusted' under `wan_carriers`, + `ipv4_acl_in` is also required on all WAN interfaces. + """ + wan_circuit_id: str | None + """ + The WAN circuit ID for this interface. + This is not rendered in the configuration but used for WAN + designs. + """ + connected_to_pathfinder: bool + """ + For a WAN interface (`wan_carrier` is set), allow to disable the static tunnel towards Pathfinders. + + Default value: `True` + """ + cv_pathfinder_internet_exit: CvPathfinderInternetExit + """ + PREVIEW: This key is in preview mode + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the interface in the final EOS configuration.""" + flow_tracking: FlowTracking + """ + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + """ + structured_config: StructuredConfig + """ + Custom structured config for the Ethernet interface. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | None | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + dhcp_ip: str | None | UndefinedType = Undefined, + public_ip: str | None | UndefinedType = Undefined, + encapsulation_dot1q_vlan: int | None | UndefinedType = Undefined, + dhcp_accept_default_route: bool | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + speed: str | None | UndefinedType = Undefined, + peer: str | None | UndefinedType = Undefined, + peer_interface: str | None | UndefinedType = Undefined, + peer_ip: str | None | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + ipv4_acl_in: str | None | UndefinedType = Undefined, + ipv4_acl_out: str | None | UndefinedType = Undefined, + static_routes: StaticRoutes | UndefinedType = Undefined, + qos_profile: str | None | UndefinedType = Undefined, + wan_carrier: str | None | UndefinedType = Undefined, + wan_circuit_id: str | None | UndefinedType = Undefined, + connected_to_pathfinder: bool | UndefinedType = Undefined, + cv_pathfinder_internet_exit: CvPathfinderInternetExit | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L3InterfacesItem. + + + Subclass of AvdModel. + + Args: + profile: L3 interface profile name. Profile defined under `l3_interface_profiles`. + name: + Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. + For a + subinterface, the parent physical interface is automatically created. + description: + Interface description. + If not set a default description will be configured with '[[ + ]]'. + ip_address: Node IPv4 address/Mask or 'dhcp'. + dhcp_ip: + When the `ip_address` is `dhcp`, this optional field allows to indicate the expected + IPv4 address + (without mask) to be allocated on the interface if known. + This is not rendered in the configuration + but can be used for substitution of 'interface_ip' in the Access-list + set under `ipv4_acl_in` and + `ipv4_acl_out`. + public_ip: + Node IPv4 address (no mask). + + This is used to get the public IP (if known) when the device is behind + NAT. + This is only used for `wan_rr` routers (AutoVPN RRs and Pathfinders) to determine the Public IP + with the following preference: + `wan_route_servers.path_groups.interfaces.ip_address` + -> + `l3_interfaces.public_ip` + -> `l3_interfaces.ip_address` + + The determined Public IP is used + by WAN routers when peering with this interface. + encapsulation_dot1q_vlan: + For subinterfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + dhcp_accept_default_route: Accept a default route from DHCP if `ip_address` is set to `dhcp`. + enabled: Enable or Shutdown the interface. + speed: + Speed should be set in the format `` or `forced ` or `auto + `. + peer: The peer device name. Used for description and documentation. + peer_interface: The peer device interface. Used for description and documentation. + peer_ip: + The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true + and `ip` is an IP address. + bgp: + Enforce IPv4 BGP peering for the peer + + Subclass of AvdModel. + ipv4_acl_in: + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + Required + for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under + `wan_carriers`. + ipv4_acl_out: + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + static_routes: + Configure IPv4 static routes pointing to `peer_ip`. + + Subclass of AvdList with `StaticRoutesItem` + items. + qos_profile: QOS service profile. + wan_carrier: + The WAN carrier this interface is connected to. + This is used to infer the path-groups in which this + interface should be configured. + Unless the carrier is marked as 'trusted' under `wan_carriers`, + `ipv4_acl_in` is also required on all WAN interfaces. + wan_circuit_id: + The WAN circuit ID for this interface. + This is not rendered in the configuration but used for WAN + designs. + connected_to_pathfinder: For a WAN interface (`wan_carrier` is set), allow to disable the static tunnel towards Pathfinders. + cv_pathfinder_internet_exit: + PREVIEW: This key is in preview mode + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the interface in the final EOS configuration. + flow_tracking: + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + structured_config: + Custom structured config for the Ethernet interface. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): + """Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + L3Interfaces._item_type = L3InterfacesItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "downlink_pools": {"type": DownlinkPools}, + "id": {"type": int}, + "platform": {"type": str}, + "mac_address": {"type": str}, + "system_mac_address": {"type": str}, + "serial_number": {"type": str}, + "rack": {"type": str}, + "mgmt_ip": {"type": str}, + "mgmt_gateway": {"type": str}, + "ipv6_mgmt_ip": {"type": str}, + "ipv6_mgmt_gateway": {"type": str}, + "mgmt_interface": {"type": str}, + "link_tracking": {"type": LinkTracking}, + "lacp_port_id_range": {"type": LacpPortIdRange}, + "always_configure_ip_routing": {"type": bool, "default": False}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "uplink_type": {"type": str}, + "uplink_ipv4_pool": {"type": str}, + "uplink_interfaces": {"type": UplinkInterfaces}, + "uplink_switch_interfaces": {"type": UplinkSwitchInterfaces}, + "uplink_switches": {"type": UplinkSwitches}, + "uplink_interface_speed": {"type": str}, + "uplink_switch_interface_speed": {"type": str}, + "uplink_mtu": {"type": int}, + "max_uplink_switches": {"type": int}, + "max_parallel_uplinks": {"type": int, "default": 1}, + "uplink_bfd": {"type": bool, "default": False}, + "uplink_native_vlan": {"type": int}, + "uplink_ptp": {"type": UplinkPtp}, + "uplink_macsec": {"type": UplinkMacsec}, + "uplink_port_channel_id": {"type": int}, + "uplink_switch_port_channel_id": {"type": int}, + "uplink_structured_config": {"type": dict}, + "mlag_port_channel_structured_config": {"type": MlagPortChannelStructuredConfig}, + "mlag_peer_vlan_structured_config": {"type": MlagPeerVlanStructuredConfig}, + "mlag_peer_l3_vlan_structured_config": {"type": MlagPeerL3VlanStructuredConfig}, + "short_esi": {"type": str}, + "isis_system_id_prefix": {"type": str}, + "isis_maximum_paths": {"type": int}, + "is_type": {"type": str}, + "node_sid_base": {"type": int, "default": 0}, + "loopback_ipv4_pool": {"type": str}, + "loopback_ipv4_address": {"type": str}, + "vtep_loopback_ipv4_pool": {"type": str}, + "vtep_loopback_ipv4_address": {"type": str}, + "loopback_ipv4_offset": {"type": int, "default": 0}, + "loopback_ipv6_pool": {"type": str}, + "loopback_ipv6_offset": {"type": int, "default": 0}, + "vtep": {"type": bool}, + "vtep_loopback": {"type": str}, + "bgp_as": {"type": str}, + "bgp_defaults": {"type": BgpDefaults}, + "evpn_role": {"type": str}, + "evpn_route_servers": {"type": EvpnRouteServers}, + "evpn_services_l2_only": {"type": bool, "default": False}, + "filter": {"type": Filter}, + "igmp_snooping_enabled": {"type": bool}, + "evpn_gateway": {"type": EvpnGateway}, + "ipvpn_gateway": {"type": IpvpnGateway}, + "mlag": {"type": bool, "default": True}, + "mlag_dual_primary_detection": {"type": bool, "default": False}, + "mlag_ibgp_origin_incomplete": {"type": bool, "default": True}, + "mlag_interfaces": {"type": MlagInterfaces}, + "mlag_interfaces_speed": {"type": str}, + "mlag_peer_l3_vlan": {"type": int, "default": 4093}, + "mlag_peer_l3_ipv4_pool": {"type": str}, + "mlag_peer_vlan": {"type": int, "default": 4094}, + "mlag_peer_link_allowed_vlans": {"type": str}, + "mlag_peer_address_family": {"type": str, "default": "ipv4"}, + "mlag_peer_ipv4_pool": {"type": str}, + "mlag_peer_ipv6_pool": {"type": str}, + "mlag_port_channel_id": {"type": int}, + "mlag_domain_id": {"type": str}, + "spanning_tree_mode": {"type": str}, + "spanning_tree_priority": {"type": int, "default": 32768}, + "spanning_tree_root_super": {"type": bool, "default": False}, + "virtual_router_mac_address": {"type": str}, + "inband_mgmt_interface": {"type": str}, + "inband_mgmt_vlan": {"type": int, "default": 4092}, + "inband_mgmt_subnet": {"type": str}, + "inband_mgmt_ip": {"type": str}, + "inband_mgmt_gateway": {"type": str}, + "inband_mgmt_ipv6_address": {"type": str}, + "inband_mgmt_ipv6_subnet": {"type": str}, + "inband_mgmt_ipv6_gateway": {"type": str}, + "inband_mgmt_description": {"type": str, "default": "Inband Management"}, + "inband_mgmt_vlan_name": {"type": str, "default": "INBAND_MGMT"}, + "inband_mgmt_vrf": {"type": str, "default": "default"}, + "inband_mgmt_mtu": {"type": int, "default": 1500}, + "inband_ztp": {"type": bool, "default": False}, + "inband_ztp_lacp_fallback_delay": {"type": int, "default": 30}, + "mpls_overlay_role": {"type": str}, + "overlay_address_families": {"type": OverlayAddressFamilies}, + "mpls_route_reflectors": {"type": MplsRouteReflectors}, + "bgp_cluster_id": {"type": str}, + "ptp": {"type": Ptp}, + "wan_role": {"type": str}, + "cv_pathfinder_transit_mode": {"type": str}, + "cv_pathfinder_region": {"type": str}, + "cv_pathfinder_site": {"type": str}, + "wan_ha": {"type": WanHa}, + "dps_mss_ipv4": {"type": str, "default": "auto"}, + "l3_interfaces": {"type": L3Interfaces}, + "data_plane_cpu_allocation_max": {"type": int}, + "flow_tracker_type": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """The Node Name is used as "hostname".""" + downlink_pools: DownlinkPools + """ + IPv4 pools used for links to downlink switches. Set this on the parent switch. Cannot be combined + with `uplink_ipv4_pool` set on the downlink switch. + + Subclass of AvdList with `DownlinkPoolsItem` + items. + """ + id: int | None + """Unique identifier used for IP addressing and other algorithms.""" + platform: str | None + """Arista platform family.""" + mac_address: str | None + """Leverage to document management interface mac address.""" + system_mac_address: str | None + """ + System MAC Address in this following format: "xx:xx:xx:xx:xx:xx". + Set to the same MAC address as + available in "show version" on the device. + "system_mac_address" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + """ + serial_number: str | None + """ + Set to the Serial Number of the device. + Only used for documentation purpose in the fabric + documentation and part of the structured_config. + "serial_number" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + """ + rack: str | None + """Rack that the switch is located in (only used in snmp_settings location).""" + mgmt_ip: str | None + """Node management interface IPv4 address.""" + mgmt_gateway: str | None + """ + This key sets the management gateway for the device. It takes precedence over the global + `mgmt_gateway`. + """ + ipv6_mgmt_ip: str | None + """Node management interface IPv6 address.""" + ipv6_mgmt_gateway: str | None + """ + This key sets the ipv6 management gateway for the device. It takes precedence over the global + `ipv6_mgmt_gateway`. + """ + mgmt_interface: str | None + """ + Management Interface Name. + Default -> platform_management_interface -> mgmt_interface -> + "Management1". + """ + link_tracking: LinkTracking + """ + This configures the Link Tracking Group on a switch as well as adds the p2p-uplinks of the switch as + the upstream interfaces. + Useful in EVPN multhoming designs. + + + Subclass of AvdModel. + """ + lacp_port_id_range: LacpPortIdRange + """ + This will generate the "lacp port-id range", "begin" and "end" values based on node "id" and the + number of nodes in the "node_group". + Unique LACP port-id ranges are recommended for EVPN Multihoming + designs. + + + Subclass of AvdModel. + """ + always_configure_ip_routing: bool + """ + Force configuration of "ip routing" even on L2 devices. + Use this to retain behavior of AVD versions + below 4.0.0. + + Default value: `False` + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the root level of the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + """ + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None + """ + Override the default `uplink_type` set at the `node_type_key` level. + `uplink_type` must be "p2p" if + `vtep` or `underlay_router` is true for the `node_type_key` definition. + """ + uplink_ipv4_pool: str | None + """IPv4 subnet to use to connect to uplink switches.""" + uplink_interfaces: UplinkInterfaces + """ + Local uplink interfaces. + Each list item supports range syntax that can be expanded into a list of + interfaces. + If uplink_interfaces is not defined, platform-specific defaults (defined under + default_interfaces) will be used instead. + Please note that default_interfaces are not defined by + default, you should define these yourself. + + + Subclass of AvdList with `str` items. + """ + uplink_switch_interfaces: UplinkSwitchInterfaces + """ + Interfaces located on uplink switches. + + Subclass of AvdList with `str` items. + """ + uplink_switches: UplinkSwitches + """Subclass of AvdList with `str` items.""" + uplink_interface_speed: str | None + """ + Set point-to-Point interface speed and will apply to uplink interfaces on both ends. + (Uplink switch + interface speed can be overridden with `uplink_switch_interface_speed`). + Speed should be set in the + format `` or `forced ` or `auto `. + """ + uplink_switch_interface_speed: str | None + """ + 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: int | None + """Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting.""" + max_uplink_switches: int | None + """ + 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: 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 + """ + Enable bfd on uplink interfaces. + + Default value: `False` + """ + uplink_native_vlan: int | None + """ + 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: UplinkPtp + """ + Enable PTP on all infrastructure links. + + Subclass of AvdModel. + """ + uplink_macsec: UplinkMacsec + """ + Enable MacSec on all uplinks. + + Subclass of AvdModel. + """ + uplink_port_channel_id: int | None + """ + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink Port-channel + ID will be set to the number of the lowest member interface defined under `uplink_interfaces`. + For + example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ Eth11/1, Eth22/1 ] -> ID 111 + For + MLAG port-channels ID will be based on the lowest member interface on the first MLAG switch. + This + option overrides the default behavior and statically sets the local Port-channel ID. + Note! Make sure + the ID is unique and does not overlap with autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between 1 and 2000 and both MLAG switches must have the same + value. + """ + uplink_switch_port_channel_id: int | None + """ + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink switch Port- + channel ID will be set to the number of the first interface defined under + `uplink_switch_interfaces`. + For example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ + Eth11/1, Eth22/1 ] -> ID 111 + For MLAG port-channels ID will be based on the lowest member interface + on the first MLAG switch. + This option overrides the default behavior and statically sets the Port- + channel ID on the uplink switch. + Note! Make sure the ID is unique and does not overlap with + autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between + 1 and 2000 and both MLAG switches must have the same value. + """ + uplink_structured_config: dict + """ + Custom structured config applied to "uplink_interfaces", and "uplink_switch_interfaces". + When + uplink_type == "p2p", custom structured config added under ethernet_interfaces.[name=] + for eos_cli_config_gen overrides the settings on the ethernet interface level. + When uplink_type == + "port-channel", custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen overrides the settings on the port-channel interface level. + "uplink_structured_config" is applied after "structured_config", so it can override + "structured_config" defined on node-level. + Note! The content of this dictionary is _not_ validated + by the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + """ + mlag_port_channel_structured_config: MlagPortChannelStructuredConfig + """ + Custom structured config applied to MLAG peer link port-channel id. + Added under + port_channel_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the + port-channel interface level. + "mlag_port_channel_structured_config" is applied after + "structured_config", so it can override "structured_config" defined on node-level. + + + Subclass of + AvdModel. + """ + mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig + """ + Custom structured config applied to MLAG Peer Link (control link) SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_vlan_structured_config" is applied after "structured_config", so it can + override "structured_config" defined on node-level. + + + Subclass of AvdModel. + """ + mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig + """ + Custom structured config applied to MLAG underlay L3 peering SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_l3_vlan_structured_config" is applied after "structured_config", so it + can override "structured_config" defined on node-level. + + + Subclass of AvdModel. + """ + short_esi: str | None + """ + short_esi only valid for l2leaf devices using port-channel uplink. + Setting short_esi to "auto" + generates the short_esi automatically using a hash of configuration elements. + < 0000:0000:0000 | + auto >. + """ + isis_system_id_prefix: str | None + """(4.4 hexadecimal).""" + isis_maximum_paths: int | None + """Number of path to configure in ECMP for ISIS.""" + is_type: Literal["level-1-2", "level-1", "level-2"] | None + """Overrides `isis_default_is_type`.""" + node_sid_base: int + """ + Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID. + + Default value: `0` + """ + loopback_ipv4_pool: str | None + """IPv4 subnet for Loopback0 allocation.""" + loopback_ipv4_address: str | None + """ + IPv4 address without mask for Loopback0. + When set, it takes precedence over `loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not catch duplicates. + """ + vtep_loopback_ipv4_pool: str | None + """IPv4 subnet for VTEP-Loopback allocation.""" + vtep_loopback_ipv4_address: str | None + """ + IPv4 address without mask for VTEP-Loopback. + When set, it takes precedence over + `vtep_loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not + catch duplicates. + """ + loopback_ipv4_offset: int + """ + Offset all assigned loopback IP addresses. + Required when the < loopback_ipv4_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid over-lapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv4_offset: < total # spine switches > or vice versa. + + Default value: `0` + """ + loopback_ipv6_pool: str | None + """IPv6 subnet for Loopback0 allocation.""" + loopback_ipv6_offset: int + """ + Offset all assigned loopback IPv6 addresses. + Required when the < loopback_ipv6_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid overlapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv6_offset: < total # spine switches > or vice versa. + + Default value: `0` + """ + vtep: bool | None + """ + Node is configured as a VTEP when applicable based on 'overlay_routing_protocol'. + Overrides VTEP + setting inherited from node_type_keys. + """ + vtep_loopback: str | None + """Set VXLAN source interface.""" + bgp_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + Required with eBGP. + """ + bgp_defaults: BgpDefaults + """ + List of EOS commands to apply to BGP daemon. + + Subclass of AvdList with `str` items. + """ + evpn_role: Literal["client", "server", "none"] | None + """ + Acting role in EVPN control plane. + Default is set in node_type definition from node_type_keys. + """ + evpn_route_servers: EvpnRouteServers + """ + List of nodes acting as EVPN Route-Servers / Route-Reflectors. + + Subclass of AvdList with `str` + items. + """ + evpn_services_l2_only: bool + """ + Possibility to prevent configuration of Tenant VRFs and SVIs. + Override node definition + "network_services_l3" from node_type_keys. + This allows support for centralized routing. + + Default value: `False` + """ + filter: Filter + """ + Filter L3 and L2 network services based on tenant and tags (and operation filter). + If filter is not + defined it will default to all. + + + Subclass of AvdModel. + """ + igmp_snooping_enabled: bool | None + """Activate or deactivate IGMP snooping on device level.""" + evpn_gateway: EvpnGateway + """ + Node is acting as EVPN Multi-Domain Gateway. + New BGP peer-group is generated between EVPN GWs in + different domains or between GWs and Route Servers. + Name can be changed under + "bgp_peer_groups.evpn_overlay_core" variable. + L3 rechability for different EVPN GWs must be already + in place, it is recommended to use DCI & L3 Edge if Route Servers and GWs are not defined under the + same Ansible inventory. + + + Subclass of AvdModel. + """ + ipvpn_gateway: IpvpnGateway + """ + Node is acting as IP-VPN Gateway for EVPN to MPLS-IP-VPN Interworking. The BGP peer group used for + this is "bgp_peer_groups.ipvpn_gateway_peers". + L3 Reachability is required for this to work, the + preferred method to establish underlay connectivity is to use core_interfaces. + + + Subclass of + AvdModel. + """ + mlag: bool + """ + Enable / Disable auto MLAG, when two nodes are defined in node group. + + Default value: `True` + """ + mlag_dual_primary_detection: bool + """ + Enable / Disable MLAG dual primary detection. + + Default value: `False` + """ + mlag_ibgp_origin_incomplete: bool + """ + Set origin of routes received from MLAG iBGP peer to incomplete. + The purpose is to optimize routing + for leaf loopbacks from spine perspective and + avoid suboptimal routing via peerlink for control + plane traffic. + + Default value: `True` + """ + mlag_interfaces: MlagInterfaces + """ + Each list item supports range syntax that can be expanded into a list of interfaces. + Required when + MLAG leafs are present in the topology. + + + Subclass of AvdList with `str` items. + """ + mlag_interfaces_speed: str | None + """ + Set MLAG interface speed. + Speed should be set in the format `` or `forced + ` or `auto `. + """ + mlag_peer_l3_vlan: int + """ + Underlay L3 peering SVI interface id. + If set to 0 or the same vlan as mlag_peer_vlan, the + mlag_peer_vlan will be used for L3 peering. + + Default value: `4093` + """ + mlag_peer_l3_ipv4_pool: str | None + """ + IP address pool used for MLAG underlay L3 peering. IP is derived from the node id. + Required when + MLAG leafs present in topology and they are using a separate L3 peering VLAN. + """ + mlag_peer_vlan: int + """ + MLAG Peer Link (control link) SVI interface id. + + Default value: `4094` + """ + mlag_peer_link_allowed_vlans: str | None + mlag_peer_address_family: Literal["ipv4", "ipv6"] + """ + IP address family used to establish MLAG Peer Link (control link). + `ipv6` requires EOS version + 4.31.1F or higher. + Note: `ipv6` is not supported in combination with a common MLAG peer link VLAN + (ex. `mlag_peer_l3_vlan` set to 4094). + + Default value: `"ipv4"` + """ + mlag_peer_ipv4_pool: str | None + """ + IPv4 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv4` (default). + """ + mlag_peer_ipv6_pool: str | None + """ + IPv6 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv6`. + """ + mlag_port_channel_id: int | None + """ + If not set, the mlag port-channel id is generated based on the digits of the first interface present + in 'mlag_interfaces'. + Valid port-channel id numbers are < 1-2000 > for EOS < 4.25.0F and < 1 - + 999999 > for EOS >= 4.25.0F. + """ + mlag_domain_id: str | None + """MLAG Domain ID. If not set the node group name (Set with "group" key) will be used.""" + spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None + spanning_tree_priority: int + """ + Spanning-tree priority configured for the selected mode. + For `rapid-pvst` the priority can also be + set per VLAN under network services. + + Default value: `32768` + """ + spanning_tree_root_super: bool + """Default value: `False`""" + virtual_router_mac_address: str | None + """Virtual router mac address for anycast gateway.""" + inband_mgmt_interface: str | None + """ + Pointer to interface used for inband management. + All configuration must be done using other data + models like network services or structured_config. + 'inband_mgmt_interface' is only used to refer to + this interface as source in various management protocol settings (future feature). + + On L2 switches, + this defaults to Vlan if either 'inband_mgmt_subnet' or 'inband_mgmt_ip' is set. + """ + inband_mgmt_vlan: int + """ + VLAN number used for inband management on L2 switches (switches using port-channel trunks as + uplinks). + When using 'inband_mgmt_subnet' the VLAN and SVIs will be created automatically on this + switch as well as all 'uplink_switches'. + When using 'inband_mgmt_ip' the VLAN and SVI will only be + created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be + created using network services data models. + + Default value: `4092` + """ + inband_mgmt_subnet: str | None + """ + Optional IP subnet assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ip virtual-router" and host-route injection based on + ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + + 3 + + GW on l2leafs : + 1 + Assign range larger than total l2leafs + 5 + Setting is ignored if 'inband_mgmt_ip' is set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + """ + inband_mgmt_ip: str | None + """ + IP address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_subnet', hence all behavior of 'inband_mgmt_subnet' is removed. + + If this is set the + VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN and SVI on + the parent switches must be created using network services data models. + + This setting is applicable + to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_gateway: str | None + """ + Default gateway configured in the 'inband_mgmt_vrf' when using 'inband_mgmt_ip'. Otherwise gateway + is derived from 'inband_mgmt_subnet' if set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_address: str | None + """ + IPv6 address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_ipv6_subnet', hence the configuration of 'inband_mgmt_ipv6_subnet' is ignored. + + If this + is set the VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN + and SVI on the parent switches must be created using network services data models. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_subnet: str | None + """ + Optional IPv6 prefix assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ipv6 virtual-router" and host-route injection based + on ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN + extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + 3 + + GW on l2leafs : + 1 + Assign range larger than + total l2leafs + 5 + + Setting is ignored if 'inband_mgmt_ipv6_address' is set. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_gateway: str | None + """ + Default gateway configured in the 'inband_mgmt_vrf'. + Used when `inband_mgmt_ipv6_address` is set. + Ignored when 'inband_mgmt_ipv6_subnet' is set (first IP in subnet used as gateway). + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_description: str + """ + Description configured on the Inband Management SVI. + + This setting is only applied on the devices + where it is set, it does not automatically affect any parent/child devices configuration, so it must + be set on each applicable node/node-group/node-type as needed. + + Default value: `"Inband Management"` + """ + inband_mgmt_vlan_name: str + """ + Name configured on the Inband Management VLAN. + This setting is only applied on the devices where it + is set, it does not automatically affect any parent/child devices configuration, so it must be set + on each applicable node/node-group/node-type as needed. + + Default value: `"INBAND_MGMT"` + """ + inband_mgmt_vrf: str + """ + VRF configured on the Inband Management Interface. + The VRF is created if not already created by + other means. + This setting is only applied on the devices where it is set, it does not automatically + affect any parent/child devices configuration, so it must be set on each applicable node/node- + group/node-type as needed. + + Default value: `"default"` + """ + inband_mgmt_mtu: int + """ + MTU configured on the Inband Management Interface. + This setting is only applied on the devices where + it is set, it does not automatically affect any parent/child devices configuration, so it must be + set on each applicable node/node-group/node-type as needed. + + Default value: `1500` + """ + inband_ztp: bool + """ + Enable to configure upstream device with proper configuration to allow downstream devices to be + Zero-Touch-Provisioned over the uplink interfaces. + For L2 devices this setting also requires that + the `inband_mgmt_vlan` is set for the node. + + PREVIEW: Support for L3 devices is marked as "preview", + meaning the data models or generated configuration can change at any time. + + Default value: `False` + """ + inband_ztp_lacp_fallback_delay: int + """ + Set the LACP fallback timeout of the upstream device's port-channel towards the downstream inband + ZTP node. + This setting also requires that `inband_ztp` is set for the node. + + Default value: `30` + """ + mpls_overlay_role: Literal["client", "server", "none"] | None + """ + Set the default mpls overlay role. + Acting role in overlay control plane. + """ + overlay_address_families: OverlayAddressFamilies + """ + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + """ + mpls_route_reflectors: MplsRouteReflectors + """ + List of inventory hostname acting as MPLS route-reflectors. + + Subclass of AvdList with `str` items. + """ + bgp_cluster_id: str | None + """Set BGP cluster id.""" + ptp: Ptp + """Subclass of AvdModel.""" + wan_role: Literal["client", "server"] | None + """ + Override the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + """ + cv_pathfinder_transit_mode: Literal["region", "zone"] | None + """ + Configure the transit mode for a WAN client for CV Pathfinder designs + only when the `wan_mode` root + key is set to `cv_pathfinder`. + + 'zone' is currently not supported. + """ + cv_pathfinder_region: str | None + """ + The CV Pathfinder region name. + This key is required for WAN routers but optional for pathfinders. + The region name must be defined under 'cv_pathfinder_regions'. + """ + cv_pathfinder_site: str | None + """ + The CV Pathfinder site name. + This key is required for WAN routers but optional for pathfinders. + For + WAN routers and pathfinders with `cv_pathfinder_region`, the site name must be defined for the + relevant region under 'cv_pathfinder_regions'. + For pathfinders without `cv_pathfinder_region` set, + the site must be defined under `cv_pathfinder_global_sites`. + """ + wan_ha: WanHa + """ + PREVIEW: This key is currently not supported + + The key is supported only if `wan_mode` == `cv- + pathfinder`. + AutoVPN support is still to be determined. + + Maximum 2 devices supported by group for + HA. + + Subclass of AvdModel. + """ + dps_mss_ipv4: str + """ + IPv4 MSS value configured under "router path-selection" on WAN Devices. + + Default value: `"auto"` + """ + l3_interfaces: L3Interfaces + """ + L3 Interfaces to configure on the node. + Used to define the node for WAN interfaces when + `wan_carrier` is set. + + Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is + `name` (`str`). + """ + data_plane_cpu_allocation_max: int | None + """ + Set the maximum number of CPU used for the data plane. + This setting is useful on virtual Route + Reflectors and Pathfinders where more CPU cores should be allocated for control plane. + """ + flow_tracker_type: Literal["sampled", "hardware"] | None + """ + Set the flow tracker type. + Override the `default_flow_tracker_type`` set at the `node_type_key` + level. + `default_flow_tracker_type` default value is `sampled`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + downlink_pools: DownlinkPools | UndefinedType = Undefined, + id: int | None | UndefinedType = Undefined, + platform: str | None | UndefinedType = Undefined, + mac_address: str | None | UndefinedType = Undefined, + system_mac_address: str | None | UndefinedType = Undefined, + serial_number: str | None | UndefinedType = Undefined, + rack: str | None | UndefinedType = Undefined, + mgmt_ip: str | None | UndefinedType = Undefined, + mgmt_gateway: str | None | UndefinedType = Undefined, + ipv6_mgmt_ip: str | None | UndefinedType = Undefined, + ipv6_mgmt_gateway: str | None | UndefinedType = Undefined, + mgmt_interface: str | None | UndefinedType = Undefined, + link_tracking: LinkTracking | UndefinedType = Undefined, + lacp_port_id_range: LacpPortIdRange | UndefinedType = Undefined, + always_configure_ip_routing: bool | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None | UndefinedType = Undefined, + uplink_ipv4_pool: str | None | UndefinedType = Undefined, + uplink_interfaces: UplinkInterfaces | UndefinedType = Undefined, + uplink_switch_interfaces: UplinkSwitchInterfaces | UndefinedType = Undefined, + uplink_switches: UplinkSwitches | UndefinedType = Undefined, + uplink_interface_speed: str | None | UndefinedType = Undefined, + 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 | UndefinedType = Undefined, + uplink_bfd: bool | UndefinedType = Undefined, + uplink_native_vlan: int | None | UndefinedType = Undefined, + uplink_ptp: UplinkPtp | UndefinedType = Undefined, + uplink_macsec: UplinkMacsec | UndefinedType = Undefined, + uplink_port_channel_id: int | None | UndefinedType = Undefined, + uplink_switch_port_channel_id: int | None | UndefinedType = Undefined, + uplink_structured_config: dict | UndefinedType = Undefined, + mlag_port_channel_structured_config: MlagPortChannelStructuredConfig | UndefinedType = Undefined, + mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig | UndefinedType = Undefined, + mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig | UndefinedType = Undefined, + short_esi: str | None | UndefinedType = Undefined, + isis_system_id_prefix: str | None | UndefinedType = Undefined, + isis_maximum_paths: int | None | UndefinedType = Undefined, + is_type: Literal["level-1-2", "level-1", "level-2"] | None | UndefinedType = Undefined, + node_sid_base: int | UndefinedType = Undefined, + loopback_ipv4_pool: str | None | UndefinedType = Undefined, + loopback_ipv4_address: str | None | UndefinedType = Undefined, + vtep_loopback_ipv4_pool: str | None | UndefinedType = Undefined, + vtep_loopback_ipv4_address: str | None | UndefinedType = Undefined, + loopback_ipv4_offset: int | UndefinedType = Undefined, + loopback_ipv6_pool: str | None | UndefinedType = Undefined, + loopback_ipv6_offset: int | UndefinedType = Undefined, + vtep: bool | None | UndefinedType = Undefined, + vtep_loopback: str | None | UndefinedType = Undefined, + bgp_as: str | None | UndefinedType = Undefined, + bgp_defaults: BgpDefaults | UndefinedType = Undefined, + evpn_role: Literal["client", "server", "none"] | None | UndefinedType = Undefined, + evpn_route_servers: EvpnRouteServers | UndefinedType = Undefined, + evpn_services_l2_only: bool | UndefinedType = Undefined, + filter: Filter | UndefinedType = Undefined, + igmp_snooping_enabled: bool | None | UndefinedType = Undefined, + evpn_gateway: EvpnGateway | UndefinedType = Undefined, + ipvpn_gateway: IpvpnGateway | UndefinedType = Undefined, + mlag: bool | UndefinedType = Undefined, + mlag_dual_primary_detection: bool | UndefinedType = Undefined, + mlag_ibgp_origin_incomplete: bool | UndefinedType = Undefined, + mlag_interfaces: MlagInterfaces | UndefinedType = Undefined, + mlag_interfaces_speed: str | None | UndefinedType = Undefined, + mlag_peer_l3_vlan: int | UndefinedType = Undefined, + mlag_peer_l3_ipv4_pool: str | None | UndefinedType = Undefined, + mlag_peer_vlan: int | UndefinedType = Undefined, + mlag_peer_link_allowed_vlans: str | None | UndefinedType = Undefined, + mlag_peer_address_family: Literal["ipv4", "ipv6"] | UndefinedType = Undefined, + mlag_peer_ipv4_pool: str | None | UndefinedType = Undefined, + mlag_peer_ipv6_pool: str | None | UndefinedType = Undefined, + mlag_port_channel_id: int | None | UndefinedType = Undefined, + mlag_domain_id: str | None | UndefinedType = Undefined, + spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None | UndefinedType = Undefined, + spanning_tree_priority: int | UndefinedType = Undefined, + spanning_tree_root_super: bool | UndefinedType = Undefined, + virtual_router_mac_address: str | None | UndefinedType = Undefined, + inband_mgmt_interface: str | None | UndefinedType = Undefined, + inband_mgmt_vlan: int | UndefinedType = Undefined, + inband_mgmt_subnet: str | None | UndefinedType = Undefined, + inband_mgmt_ip: str | None | UndefinedType = Undefined, + inband_mgmt_gateway: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_address: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_subnet: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_gateway: str | None | UndefinedType = Undefined, + inband_mgmt_description: str | UndefinedType = Undefined, + inband_mgmt_vlan_name: str | UndefinedType = Undefined, + inband_mgmt_vrf: str | UndefinedType = Undefined, + inband_mgmt_mtu: int | UndefinedType = Undefined, + inband_ztp: bool | UndefinedType = Undefined, + inband_ztp_lacp_fallback_delay: int | UndefinedType = Undefined, + mpls_overlay_role: Literal["client", "server", "none"] | None | UndefinedType = Undefined, + overlay_address_families: OverlayAddressFamilies | UndefinedType = Undefined, + mpls_route_reflectors: MplsRouteReflectors | UndefinedType = Undefined, + bgp_cluster_id: str | None | UndefinedType = Undefined, + ptp: Ptp | UndefinedType = Undefined, + wan_role: Literal["client", "server"] | None | UndefinedType = Undefined, + cv_pathfinder_transit_mode: Literal["region", "zone"] | None | UndefinedType = Undefined, + cv_pathfinder_region: str | None | UndefinedType = Undefined, + cv_pathfinder_site: str | None | UndefinedType = Undefined, + wan_ha: WanHa | UndefinedType = Undefined, + dps_mss_ipv4: str | UndefinedType = Undefined, + l3_interfaces: L3Interfaces | UndefinedType = Undefined, + data_plane_cpu_allocation_max: int | None | UndefinedType = Undefined, + flow_tracker_type: Literal["sampled", "hardware"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NodesItem. + + + Subclass of AvdModel. + + Args: + name: The Node Name is used as "hostname". + downlink_pools: + IPv4 pools used for links to downlink switches. Set this on the parent switch. Cannot be combined + with `uplink_ipv4_pool` set on the downlink switch. + + Subclass of AvdList with `DownlinkPoolsItem` + items. + id: Unique identifier used for IP addressing and other algorithms. + platform: Arista platform family. + mac_address: Leverage to document management interface mac address. + system_mac_address: + System MAC Address in this following format: "xx:xx:xx:xx:xx:xx". + Set to the same MAC address as + available in "show version" on the device. + "system_mac_address" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + serial_number: + Set to the Serial Number of the device. + Only used for documentation purpose in the fabric + documentation and part of the structured_config. + "serial_number" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + rack: Rack that the switch is located in (only used in snmp_settings location). + mgmt_ip: Node management interface IPv4 address. + mgmt_gateway: + This key sets the management gateway for the device. It takes precedence over the global + `mgmt_gateway`. + ipv6_mgmt_ip: Node management interface IPv6 address. + ipv6_mgmt_gateway: + This key sets the ipv6 management gateway for the device. It takes precedence over the global + `ipv6_mgmt_gateway`. + mgmt_interface: + Management Interface Name. + Default -> platform_management_interface -> mgmt_interface -> + "Management1". + link_tracking: + This configures the Link Tracking Group on a switch as well as adds the p2p-uplinks of the switch as + the upstream interfaces. + Useful in EVPN multhoming designs. + + + Subclass of AvdModel. + lacp_port_id_range: + This will generate the "lacp port-id range", "begin" and "end" values based on node "id" and the + number of nodes in the "node_group". + Unique LACP port-id ranges are recommended for EVPN Multihoming + designs. + + + Subclass of AvdModel. + always_configure_ip_routing: + Force configuration of "ip routing" even on L2 devices. + Use this to retain behavior of AVD versions + below 4.0.0. + raw_eos_cli: EOS CLI rendered directly on the root level of the final EOS configuration. + structured_config: + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + uplink_type: + Override the default `uplink_type` set at the `node_type_key` level. + `uplink_type` must be "p2p" if + `vtep` or `underlay_router` is true for the `node_type_key` definition. + uplink_ipv4_pool: IPv4 subnet to use to connect to uplink switches. + uplink_interfaces: + Local uplink interfaces. + Each list item supports range syntax that can be expanded into a list of + interfaces. + If uplink_interfaces is not defined, platform-specific defaults (defined under + default_interfaces) will be used instead. + Please note that default_interfaces are not defined by + default, you should define these yourself. + + + Subclass of AvdList with `str` items. + uplink_switch_interfaces: + Interfaces located on uplink switches. + + Subclass of AvdList with `str` items. + uplink_switches: Subclass of AvdList with `str` items. + uplink_interface_speed: + Set point-to-Point interface speed and will apply to uplink interfaces on both ends. + (Uplink switch + interface speed can be overridden with `uplink_switch_interface_speed`). + Speed should be set in the + format `` or `forced ` or `auto `. + uplink_switch_interface_speed: + 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: Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting. + max_uplink_switches: + 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: + 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: Enable bfd on uplink interfaces. + uplink_native_vlan: + 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: + Enable PTP on all infrastructure links. + + Subclass of AvdModel. + uplink_macsec: + Enable MacSec on all uplinks. + + Subclass of AvdModel. + uplink_port_channel_id: + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink Port-channel + ID will be set to the number of the lowest member interface defined under `uplink_interfaces`. + For + example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ Eth11/1, Eth22/1 ] -> ID 111 + For + MLAG port-channels ID will be based on the lowest member interface on the first MLAG switch. + This + option overrides the default behavior and statically sets the local Port-channel ID. + Note! Make sure + the ID is unique and does not overlap with autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between 1 and 2000 and both MLAG switches must have the same + value. + uplink_switch_port_channel_id: + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink switch Port- + channel ID will be set to the number of the first interface defined under + `uplink_switch_interfaces`. + For example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ + Eth11/1, Eth22/1 ] -> ID 111 + For MLAG port-channels ID will be based on the lowest member interface + on the first MLAG switch. + This option overrides the default behavior and statically sets the Port- + channel ID on the uplink switch. + Note! Make sure the ID is unique and does not overlap with + autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between + 1 and 2000 and both MLAG switches must have the same value. + uplink_structured_config: + Custom structured config applied to "uplink_interfaces", and "uplink_switch_interfaces". + When + uplink_type == "p2p", custom structured config added under ethernet_interfaces.[name=] + for eos_cli_config_gen overrides the settings on the ethernet interface level. + When uplink_type == + "port-channel", custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen overrides the settings on the port-channel interface level. + "uplink_structured_config" is applied after "structured_config", so it can override + "structured_config" defined on node-level. + Note! The content of this dictionary is _not_ validated + by the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + mlag_port_channel_structured_config: + Custom structured config applied to MLAG peer link port-channel id. + Added under + port_channel_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the + port-channel interface level. + "mlag_port_channel_structured_config" is applied after + "structured_config", so it can override "structured_config" defined on node-level. + + + Subclass of + AvdModel. + mlag_peer_vlan_structured_config: + Custom structured config applied to MLAG Peer Link (control link) SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_vlan_structured_config" is applied after "structured_config", so it can + override "structured_config" defined on node-level. + + + Subclass of AvdModel. + mlag_peer_l3_vlan_structured_config: + Custom structured config applied to MLAG underlay L3 peering SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_l3_vlan_structured_config" is applied after "structured_config", so it + can override "structured_config" defined on node-level. + + + Subclass of AvdModel. + short_esi: + short_esi only valid for l2leaf devices using port-channel uplink. + Setting short_esi to "auto" + generates the short_esi automatically using a hash of configuration elements. + < 0000:0000:0000 | + auto >. + isis_system_id_prefix: (4.4 hexadecimal). + isis_maximum_paths: Number of path to configure in ECMP for ISIS. + is_type: Overrides `isis_default_is_type`. + node_sid_base: Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID. + loopback_ipv4_pool: IPv4 subnet for Loopback0 allocation. + loopback_ipv4_address: + IPv4 address without mask for Loopback0. + When set, it takes precedence over `loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not catch duplicates. + vtep_loopback_ipv4_pool: IPv4 subnet for VTEP-Loopback allocation. + vtep_loopback_ipv4_address: + IPv4 address without mask for VTEP-Loopback. + When set, it takes precedence over + `vtep_loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not + catch duplicates. + loopback_ipv4_offset: + Offset all assigned loopback IP addresses. + Required when the < loopback_ipv4_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid over-lapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv4_offset: < total # spine switches > or vice versa. + loopback_ipv6_pool: IPv6 subnet for Loopback0 allocation. + loopback_ipv6_offset: + Offset all assigned loopback IPv6 addresses. + Required when the < loopback_ipv6_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid overlapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv6_offset: < total # spine switches > or vice versa. + vtep: + Node is configured as a VTEP when applicable based on 'overlay_routing_protocol'. + Overrides VTEP + setting inherited from node_type_keys. + vtep_loopback: Set VXLAN source interface. + bgp_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + Required with eBGP. + bgp_defaults: + List of EOS commands to apply to BGP daemon. + + Subclass of AvdList with `str` items. + evpn_role: + Acting role in EVPN control plane. + Default is set in node_type definition from node_type_keys. + evpn_route_servers: + List of nodes acting as EVPN Route-Servers / Route-Reflectors. + + Subclass of AvdList with `str` + items. + evpn_services_l2_only: + Possibility to prevent configuration of Tenant VRFs and SVIs. + Override node definition + "network_services_l3" from node_type_keys. + This allows support for centralized routing. + filter: + Filter L3 and L2 network services based on tenant and tags (and operation filter). + If filter is not + defined it will default to all. + + + Subclass of AvdModel. + igmp_snooping_enabled: Activate or deactivate IGMP snooping on device level. + evpn_gateway: + Node is acting as EVPN Multi-Domain Gateway. + New BGP peer-group is generated between EVPN GWs in + different domains or between GWs and Route Servers. + Name can be changed under + "bgp_peer_groups.evpn_overlay_core" variable. + L3 rechability for different EVPN GWs must be already + in place, it is recommended to use DCI & L3 Edge if Route Servers and GWs are not defined under the + same Ansible inventory. + + + Subclass of AvdModel. + ipvpn_gateway: + Node is acting as IP-VPN Gateway for EVPN to MPLS-IP-VPN Interworking. The BGP peer group used for + this is "bgp_peer_groups.ipvpn_gateway_peers". + L3 Reachability is required for this to work, the + preferred method to establish underlay connectivity is to use core_interfaces. + + + Subclass of + AvdModel. + mlag: Enable / Disable auto MLAG, when two nodes are defined in node group. + mlag_dual_primary_detection: Enable / Disable MLAG dual primary detection. + mlag_ibgp_origin_incomplete: + Set origin of routes received from MLAG iBGP peer to incomplete. + The purpose is to optimize routing + for leaf loopbacks from spine perspective and + avoid suboptimal routing via peerlink for control + plane traffic. + mlag_interfaces: + Each list item supports range syntax that can be expanded into a list of interfaces. + Required when + MLAG leafs are present in the topology. + + + Subclass of AvdList with `str` items. + mlag_interfaces_speed: + Set MLAG interface speed. + Speed should be set in the format `` or `forced + ` or `auto `. + mlag_peer_l3_vlan: + Underlay L3 peering SVI interface id. + If set to 0 or the same vlan as mlag_peer_vlan, the + mlag_peer_vlan will be used for L3 peering. + mlag_peer_l3_ipv4_pool: + IP address pool used for MLAG underlay L3 peering. IP is derived from the node id. + Required when + MLAG leafs present in topology and they are using a separate L3 peering VLAN. + mlag_peer_vlan: MLAG Peer Link (control link) SVI interface id. + mlag_peer_link_allowed_vlans: mlag_peer_link_allowed_vlans + mlag_peer_address_family: + IP address family used to establish MLAG Peer Link (control link). + `ipv6` requires EOS version + 4.31.1F or higher. + Note: `ipv6` is not supported in combination with a common MLAG peer link VLAN + (ex. `mlag_peer_l3_vlan` set to 4094). + mlag_peer_ipv4_pool: + IPv4 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv4` (default). + mlag_peer_ipv6_pool: + IPv6 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv6`. + mlag_port_channel_id: + If not set, the mlag port-channel id is generated based on the digits of the first interface present + in 'mlag_interfaces'. + Valid port-channel id numbers are < 1-2000 > for EOS < 4.25.0F and < 1 - + 999999 > for EOS >= 4.25.0F. + mlag_domain_id: MLAG Domain ID. If not set the node group name (Set with "group" key) will be used. + spanning_tree_mode: spanning_tree_mode + spanning_tree_priority: + Spanning-tree priority configured for the selected mode. + For `rapid-pvst` the priority can also be + set per VLAN under network services. + spanning_tree_root_super: spanning_tree_root_super + virtual_router_mac_address: Virtual router mac address for anycast gateway. + inband_mgmt_interface: + Pointer to interface used for inband management. + All configuration must be done using other data + models like network services or structured_config. + 'inband_mgmt_interface' is only used to refer to + this interface as source in various management protocol settings (future feature). + + On L2 switches, + this defaults to Vlan if either 'inband_mgmt_subnet' or 'inband_mgmt_ip' is set. + inband_mgmt_vlan: + VLAN number used for inband management on L2 switches (switches using port-channel trunks as + uplinks). + When using 'inband_mgmt_subnet' the VLAN and SVIs will be created automatically on this + switch as well as all 'uplink_switches'. + When using 'inband_mgmt_ip' the VLAN and SVI will only be + created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be + created using network services data models. + inband_mgmt_subnet: + Optional IP subnet assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ip virtual-router" and host-route injection based on + ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + + 3 + + GW on l2leafs : + 1 + Assign range larger than total l2leafs + 5 + Setting is ignored if 'inband_mgmt_ip' is set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + inband_mgmt_ip: + IP address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_subnet', hence all behavior of 'inband_mgmt_subnet' is removed. + + If this is set the + VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN and SVI on + the parent switches must be created using network services data models. + + This setting is applicable + to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_gateway: + Default gateway configured in the 'inband_mgmt_vrf' when using 'inband_mgmt_ip'. Otherwise gateway + is derived from 'inband_mgmt_subnet' if set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + inband_mgmt_ipv6_address: + IPv6 address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_ipv6_subnet', hence the configuration of 'inband_mgmt_ipv6_subnet' is ignored. + + If this + is set the VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN + and SVI on the parent switches must be created using network services data models. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_ipv6_subnet: + Optional IPv6 prefix assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ipv6 virtual-router" and host-route injection based + on ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN + extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + 3 + + GW on l2leafs : + 1 + Assign range larger than + total l2leafs + 5 + + Setting is ignored if 'inband_mgmt_ipv6_address' is set. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_ipv6_gateway: + Default gateway configured in the 'inband_mgmt_vrf'. + Used when `inband_mgmt_ipv6_address` is set. + Ignored when 'inband_mgmt_ipv6_subnet' is set (first IP in subnet used as gateway). + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_description: + Description configured on the Inband Management SVI. + + This setting is only applied on the devices + where it is set, it does not automatically affect any parent/child devices configuration, so it must + be set on each applicable node/node-group/node-type as needed. + inband_mgmt_vlan_name: + Name configured on the Inband Management VLAN. + This setting is only applied on the devices where it + is set, it does not automatically affect any parent/child devices configuration, so it must be set + on each applicable node/node-group/node-type as needed. + inband_mgmt_vrf: + VRF configured on the Inband Management Interface. + The VRF is created if not already created by + other means. + This setting is only applied on the devices where it is set, it does not automatically + affect any parent/child devices configuration, so it must be set on each applicable node/node- + group/node-type as needed. + inband_mgmt_mtu: + MTU configured on the Inband Management Interface. + This setting is only applied on the devices where + it is set, it does not automatically affect any parent/child devices configuration, so it must be + set on each applicable node/node-group/node-type as needed. + inband_ztp: + Enable to configure upstream device with proper configuration to allow downstream devices to be + Zero-Touch-Provisioned over the uplink interfaces. + For L2 devices this setting also requires that + the `inband_mgmt_vlan` is set for the node. + + PREVIEW: Support for L3 devices is marked as "preview", + meaning the data models or generated configuration can change at any time. + inband_ztp_lacp_fallback_delay: + Set the LACP fallback timeout of the upstream device's port-channel towards the downstream inband + ZTP node. + This setting also requires that `inband_ztp` is set for the node. + mpls_overlay_role: + Set the default mpls overlay role. + Acting role in overlay control plane. + overlay_address_families: + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + mpls_route_reflectors: + List of inventory hostname acting as MPLS route-reflectors. + + Subclass of AvdList with `str` items. + bgp_cluster_id: Set BGP cluster id. + ptp: Subclass of AvdModel. + wan_role: + Override the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + cv_pathfinder_transit_mode: + Configure the transit mode for a WAN client for CV Pathfinder designs + only when the `wan_mode` root + key is set to `cv_pathfinder`. + + 'zone' is currently not supported. + cv_pathfinder_region: + The CV Pathfinder region name. + This key is required for WAN routers but optional for pathfinders. + The region name must be defined under 'cv_pathfinder_regions'. + cv_pathfinder_site: + The CV Pathfinder site name. + This key is required for WAN routers but optional for pathfinders. + For + WAN routers and pathfinders with `cv_pathfinder_region`, the site name must be defined for the + relevant region under 'cv_pathfinder_regions'. + For pathfinders without `cv_pathfinder_region` set, + the site must be defined under `cv_pathfinder_global_sites`. + wan_ha: + PREVIEW: This key is currently not supported + + The key is supported only if `wan_mode` == `cv- + pathfinder`. + AutoVPN support is still to be determined. + + Maximum 2 devices supported by group for + HA. + + Subclass of AvdModel. + dps_mss_ipv4: IPv4 MSS value configured under "router path-selection" on WAN Devices. + l3_interfaces: + L3 Interfaces to configure on the node. + Used to define the node for WAN interfaces when + `wan_carrier` is set. + + Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is + `name` (`str`). + data_plane_cpu_allocation_max: + Set the maximum number of CPU used for the data plane. + This setting is useful on virtual Route + Reflectors and Pathfinders where more CPU cores should be allocated for control plane. + flow_tracker_type: + Set the flow tracker type. + Override the `default_flow_tracker_type`` set at the `node_type_key` + level. + `default_flow_tracker_type` default value is `sampled`. + _custom_data: _custom_data + + """ + + class Nodes(AvdIndexedList[str, NodesItem]): + """Subclass of AvdIndexedList with `NodesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Nodes._item_type = NodesItem + + class LinkTracking(AvdModel): + """Subclass of AvdModel.""" + + class GroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "recovery_delay": {"type": int}, + "links_minimum": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str | None + """Tracking group name.""" + recovery_delay: int | None + """default -> platform_settings_mlag_reload_delay -> 300.""" + links_minimum: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + recovery_delay: int | None | UndefinedType = Undefined, + links_minimum: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GroupsItem. + + + Subclass of AvdModel. + + Args: + name: Tracking group name. + recovery_delay: default -> platform_settings_mlag_reload_delay -> 300. + links_minimum: links_minimum + _custom_data: _custom_data + + """ + + class Groups(AvdList[GroupsItem]): + """Subclass of AvdList with `GroupsItem` items.""" + + Groups._item_type = GroupsItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "groups": {"type": Groups, "default": lambda cls: coerce_type([{"name": "LT_GROUP1"}], target_type=cls)}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + groups: Groups + """ + Link Tracking Groups. + By default a single group named "LT_GROUP1" is defined with default values. + Any groups defined under "groups" will replace the default. + + + Subclass of AvdList with `GroupsItem` + items. + + Default value: `lambda cls: coerce_type([{"name": "LT_GROUP1"}], target_type=cls)` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + groups: + Link Tracking Groups. + By default a single group named "LT_GROUP1" is defined with default values. + Any groups defined under "groups" will replace the default. + + + Subclass of AvdList with `GroupsItem` + items. + _custom_data: _custom_data + + """ + + class LacpPortIdRange(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "size": {"type": int, "default": 128}, + "offset": {"type": int, "default": 0}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + size: int + """ + Recommended size > = number of ports in the switch. + + Default value: `128` + """ + offset: int + """ + Offset is used to avoid overlapping port-id ranges of different switches. + Useful when a "connected- + endpoint" is connected to switches in different "node_groups". + + Default value: `0` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + size: int | UndefinedType = Undefined, + offset: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LacpPortIdRange. + + + Subclass of AvdModel. + + Args: + enabled: enabled + size: Recommended size > = number of ports in the switch. + offset: + Offset is used to avoid overlapping port-id ranges of different switches. + Useful when a "connected- + endpoint" is connected to switches in different "node_groups". + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen): + """Subclass of AvdModel.""" + + class UplinkInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkInterfaces._item_type = str + + class UplinkSwitchInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkSwitchInterfaces._item_type = str + + class UplinkSwitches(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkSwitches._item_type = str + + class UplinkPtp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enable": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enable: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, enable: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + UplinkPtp. + + + Subclass of AvdModel. + + Args: + enable: enable + _custom_data: _custom_data + + """ + + class UplinkMacsec(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "_custom_data": {"type": dict}} + profile: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, profile: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + UplinkMacsec. + + + Subclass of AvdModel. + + Args: + profile: profile + _custom_data: _custom_data + + """ + + class MlagPortChannelStructuredConfig(EosCliConfigGen.PortChannelInterfacesItem): + """Subclass of AvdModel.""" + + class MlagPeerVlanStructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + class MlagPeerL3VlanStructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + class BgpDefaults(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + BgpDefaults._item_type = str + + class EvpnRouteServers(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + EvpnRouteServers._item_type = str + + class Filter(AvdModel): + """Subclass of AvdModel.""" + + class Tenants(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tenants._item_type = str + + class Tags(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tags._item_type = str + + class AllowVrfs(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AllowVrfs._item_type = str + + class DenyVrfs(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DenyVrfs._item_type = str + + class AlwaysIncludeVrfsInTenants(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AlwaysIncludeVrfsInTenants._item_type = str + + _fields: ClassVar[dict] = { + "tenants": {"type": Tenants, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "tags": {"type": Tags, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "allow_vrfs": {"type": AllowVrfs, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "deny_vrfs": {"type": DenyVrfs, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "always_include_vrfs_in_tenants": {"type": AlwaysIncludeVrfsInTenants}, + "only_vlans_in_use": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + tenants: Tenants + """ + Limit configured Network Services to those defined under these Tenants. Set to ['all'] for all + Tenants (default). + This list also limits Tenants included by `always_include_vrfs_in_tenants`. + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + tags: Tags + """ + Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default). + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + allow_vrfs: AllowVrfs + """ + Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs + (default). + This list also limits VRFs included by `always_include_vrfs_in_tenants`. + + Subclass of + AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + deny_vrfs: DenyVrfs + """ + Prevent configuration of Network Services defined under these VRFs. + This list prevents the given + VRFs to be included by any other filtering mechanism. + + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + always_include_vrfs_in_tenants: AlwaysIncludeVrfsInTenants + """ + List of tenants where VRFs will be configured even if VLANs are not included in tags. + Useful for L3 + "border" leaf. + + + Subclass of AvdList with `str` items. + """ + only_vlans_in_use: bool + """ + Only configure VLANs, SVIs, VRFs in use by connected endpoints or downstream L2 switches. + Note! This + feature only considers configuration managed by eos_designs. + This excludes structured_config, + custom_structured_configuration_, raw_eos_cli, eos_cli, custom templates, configlets etc. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + tenants: Tenants | UndefinedType = Undefined, + tags: Tags | UndefinedType = Undefined, + allow_vrfs: AllowVrfs | UndefinedType = Undefined, + deny_vrfs: DenyVrfs | UndefinedType = Undefined, + always_include_vrfs_in_tenants: AlwaysIncludeVrfsInTenants | UndefinedType = Undefined, + only_vlans_in_use: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Filter. + + + Subclass of AvdModel. + + Args: + tenants: + Limit configured Network Services to those defined under these Tenants. Set to ['all'] for all + Tenants (default). + This list also limits Tenants included by `always_include_vrfs_in_tenants`. + Subclass of AvdList with `str` items. + tags: + Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default). + Subclass of AvdList with `str` items. + allow_vrfs: + Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs + (default). + This list also limits VRFs included by `always_include_vrfs_in_tenants`. + + Subclass of + AvdList with `str` items. + deny_vrfs: + Prevent configuration of Network Services defined under these VRFs. + This list prevents the given + VRFs to be included by any other filtering mechanism. + + Subclass of AvdList with `str` items. + always_include_vrfs_in_tenants: + List of tenants where VRFs will be configured even if VLANs are not included in tags. + Useful for L3 + "border" leaf. + + + Subclass of AvdList with `str` items. + only_vlans_in_use: + Only configure VLANs, SVIs, VRFs in use by connected endpoints or downstream L2 switches. + Note! This + feature only considers configuration managed by eos_designs. + This excludes structured_config, + custom_structured_configuration_, raw_eos_cli, eos_cli, custom templates, configlets etc. + _custom_data: _custom_data + + """ + + class EvpnGateway(AvdModel): + """Subclass of AvdModel.""" + + class RemotePeersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hostname": {"type": str}, + "ip_address": {"type": str}, + "bgp_as": {"type": str}, + "_custom_data": {"type": dict}, + } + hostname: str + """Hostname of remote EVPN GW server.""" + ip_address: str | None + """Peering IP of remote Route Server.""" + bgp_as: str | None + """ + Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being + interpreted as a float number. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: str | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + bgp_as: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemotePeersItem. + + + Subclass of AvdModel. + + Args: + hostname: Hostname of remote EVPN GW server. + ip_address: Peering IP of remote Route Server. + bgp_as: + Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being + interpreted as a float number. + _custom_data: _custom_data + + """ + + class RemotePeers(AvdIndexedList[str, RemotePeersItem]): + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + + _primary_key: ClassVar[str] = "hostname" + + RemotePeers._item_type = RemotePeersItem + + class EvpnL2(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enabled: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, enabled: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + EvpnL2. + + + Subclass of AvdModel. + + Args: + enabled: enabled + _custom_data: _custom_data + + """ + + class EvpnL3(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "inter_domain": {"type": bool, "default": True}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + inter_domain: bool + """Default value: `True`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + inter_domain: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnL3. + + + Subclass of AvdModel. + + Args: + enabled: enabled + inter_domain: inter_domain + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "remote_peers": {"type": RemotePeers}, + "evpn_l2": {"type": EvpnL2}, + "evpn_l3": {"type": EvpnL3}, + "_custom_data": {"type": dict}, + } + remote_peers: RemotePeers + """ + Define remote peers of the EVPN VXLAN Gateway. + If the hostname can be found in the inventory, + ip_address and BGP ASN will be automatically populated. Manual override takes precedence. + If the + peer's hostname can not be found in the inventory, ip_address and bgp_as must be defined. + + + Subclass + of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + """ + evpn_l2: EvpnL2 + """ + Enable EVPN Gateway functionality for route-types 2 (MAC-IP) and 3 (IMET). + + Subclass of AvdModel. + """ + evpn_l3: EvpnL3 + """ + Enable EVPN Gateway functionality for route-type 5 (IP-PREFIX). + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + remote_peers: RemotePeers | UndefinedType = Undefined, + evpn_l2: EvpnL2 | UndefinedType = Undefined, + evpn_l3: EvpnL3 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnGateway. + + + Subclass of AvdModel. + + Args: + remote_peers: + Define remote peers of the EVPN VXLAN Gateway. + If the hostname can be found in the inventory, + ip_address and BGP ASN will be automatically populated. Manual override takes precedence. + If the + peer's hostname can not be found in the inventory, ip_address and bgp_as must be defined. + + + Subclass + of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + evpn_l2: + Enable EVPN Gateway functionality for route-types 2 (MAC-IP) and 3 (IMET). + + Subclass of AvdModel. + evpn_l3: + Enable EVPN Gateway functionality for route-type 5 (IP-PREFIX). + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class IpvpnGateway(AvdModel): + """Subclass of AvdModel.""" + + class AddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AddressFamilies._item_type = str + + class RemotePeersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hostname": {"type": str}, + "ip_address": {"type": str}, + "bgp_as": {"type": str}, + "_custom_data": {"type": dict}, + } + hostname: str + """Hostname of remote IPVPN Peer.""" + ip_address: str + """Peering IP of remote IPVPN Peer.""" + bgp_as: str + """ + Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For + asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted + as a float number. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: str | UndefinedType = Undefined, + ip_address: str | UndefinedType = Undefined, + bgp_as: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemotePeersItem. + + + Subclass of AvdModel. + + Args: + hostname: Hostname of remote IPVPN Peer. + ip_address: Peering IP of remote IPVPN Peer. + bgp_as: + Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For + asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted + as a float number. + _custom_data: _custom_data + + """ + + class RemotePeers(AvdIndexedList[str, RemotePeersItem]): + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + + _primary_key: ClassVar[str] = "hostname" + + RemotePeers._item_type = RemotePeersItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "evpn_domain_id": {"type": str, "default": "65535:1"}, + "ipvpn_domain_id": {"type": str, "default": "65535:2"}, + "enable_d_path": {"type": bool, "default": True}, + "maximum_routes": {"type": int, "default": 0}, + "local_as": {"type": str}, + "address_families": {"type": AddressFamilies, "default": lambda cls: coerce_type(["vpn-ipv4"], target_type=cls)}, + "remote_peers": {"type": RemotePeers}, + "_custom_data": {"type": dict}, + } + enabled: bool + evpn_domain_id: str + """ + Domain ID to assign to EVPN address family for use with D-path. Format :. + + Default value: `"65535:1"` + """ + ipvpn_domain_id: str + """ + Domain ID to assign to IPVPN address families for use with D-path. Format :. + + Default value: `"65535:2"` + """ + enable_d_path: bool + """ + Enable D-path for use with BGP bestpath selection algorithm. + + Default value: `True` + """ + maximum_routes: int + """ + Maximum routes to accept from IPVPN remote peers. + + Default value: `0` + """ + local_as: str | None + """ + Local BGP AS applied to peering with IPVPN remote peers. + BGP AS <1-4294967295> or AS number in asdot + notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number. + """ + address_families: AddressFamilies + """ + IPVPN address families to enable for remote peers. + + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["vpn-ipv4"], target_type=cls)` + """ + remote_peers: RemotePeers + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + evpn_domain_id: str | UndefinedType = Undefined, + ipvpn_domain_id: str | UndefinedType = Undefined, + enable_d_path: bool | UndefinedType = Undefined, + maximum_routes: int | UndefinedType = Undefined, + local_as: str | None | UndefinedType = Undefined, + address_families: AddressFamilies | UndefinedType = Undefined, + remote_peers: RemotePeers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpvpnGateway. + + + Subclass of AvdModel. + + Args: + enabled: enabled + evpn_domain_id: Domain ID to assign to EVPN address family for use with D-path. Format :. + ipvpn_domain_id: Domain ID to assign to IPVPN address families for use with D-path. Format :. + enable_d_path: Enable D-path for use with BGP bestpath selection algorithm. + maximum_routes: Maximum routes to accept from IPVPN remote peers. + local_as: + Local BGP AS applied to peering with IPVPN remote peers. + BGP AS <1-4294967295> or AS number in asdot + notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number. + address_families: + IPVPN address families to enable for remote peers. + + Subclass of AvdList with `str` items. + remote_peers: Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + _custom_data: _custom_data + + """ + + class MlagInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MlagInterfaces._item_type = str + + class OverlayAddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + OverlayAddressFamilies._item_type = str + + class MplsRouteReflectors(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MplsRouteReflectors._item_type = str + + class Ptp(AvdModel): + """Subclass of AvdModel.""" + + class Dscp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"general_messages": {"type": int}, "event_messages": {"type": int}, "_custom_data": {"type": dict}} + general_messages: int | None + event_messages: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + general_messages: int | None | UndefinedType = Undefined, + event_messages: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dscp. + + + Subclass of AvdModel. + + Args: + general_messages: general_messages + event_messages: event_messages + _custom_data: _custom_data + + """ + + class Monitor(AvdModel): + """Subclass of AvdModel.""" + + class Threshold(AvdModel): + """Subclass of AvdModel.""" + + class Drop(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "offset_from_master": {"type": int}, + "mean_path_delay": {"type": int}, + "_custom_data": {"type": dict}, + } + offset_from_master: int | None + mean_path_delay: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + offset_from_master: int | None | UndefinedType = Undefined, + mean_path_delay: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Drop. + + + Subclass of AvdModel. + + Args: + offset_from_master: offset_from_master + mean_path_delay: mean_path_delay + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "offset_from_master": {"type": int, "default": 250}, + "mean_path_delay": {"type": int, "default": 1500}, + "drop": {"type": Drop}, + "_custom_data": {"type": dict}, + } + offset_from_master: int + """Default value: `250`""" + mean_path_delay: int + """Default value: `1500`""" + drop: Drop + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + offset_from_master: int | UndefinedType = Undefined, + mean_path_delay: int | UndefinedType = Undefined, + drop: Drop | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Threshold. + + + Subclass of AvdModel. + + Args: + offset_from_master: offset_from_master + mean_path_delay: mean_path_delay + drop: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MissingMessage(AvdModel): + """Subclass of AvdModel.""" + + class Intervals(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "announce": {"type": int}, + "follow_up": {"type": int}, + "sync": {"type": int}, + "_custom_data": {"type": dict}, + } + announce: int | None + follow_up: int | None + sync: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + announce: int | None | UndefinedType = Undefined, + follow_up: int | None | UndefinedType = Undefined, + sync: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Intervals. + + + Subclass of AvdModel. + + Args: + announce: announce + follow_up: follow_up + sync: sync + _custom_data: _custom_data + + """ + + class SequenceIds(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "announce": {"type": int, "default": 3}, + "delay_resp": {"type": int, "default": 3}, + "follow_up": {"type": int, "default": 3}, + "sync": {"type": int, "default": 3}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + announce: int + """Default value: `3`""" + delay_resp: int + """Default value: `3`""" + follow_up: int + """Default value: `3`""" + sync: int + """Default value: `3`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + announce: int | UndefinedType = Undefined, + delay_resp: int | UndefinedType = Undefined, + follow_up: int | UndefinedType = Undefined, + sync: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceIds. + + + Subclass of AvdModel. + + Args: + enabled: enabled + announce: announce + delay_resp: delay_resp + follow_up: follow_up + sync: sync + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "intervals": {"type": Intervals}, + "sequence_ids": {"type": SequenceIds}, + "_custom_data": {"type": dict}, + } + intervals: Intervals + """Subclass of AvdModel.""" + sequence_ids: SequenceIds + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + intervals: Intervals | UndefinedType = Undefined, + sequence_ids: SequenceIds | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingMessage. + + + Subclass of AvdModel. + + Args: + intervals: Subclass of AvdModel. + sequence_ids: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "threshold": {"type": Threshold}, + "missing_message": {"type": MissingMessage}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + threshold: Threshold + """Subclass of AvdModel.""" + missing_message: MissingMessage + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + threshold: Threshold | UndefinedType = Undefined, + missing_message: MissingMessage | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Monitor. + + + Subclass of AvdModel. + + Args: + enabled: enabled + threshold: Subclass of AvdModel. + missing_message: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "profile": {"type": str}, + "mlag": {"type": bool, "default": False}, + "domain": {"type": int, "default": 127}, + "priority1": {"type": int}, + "priority2": {"type": int}, + "auto_clock_identity": {"type": bool}, + "clock_identity_prefix": {"type": str, "default": "00:1C:73"}, + "clock_identity": {"type": str}, + "source_ip": {"type": str}, + "mode": {"type": str, "default": "boundary"}, + "mode_one_step": {"type": bool, "default": False}, + "ttl": {"type": int}, + "forward_unicast": {"type": bool, "default": False}, + "dscp": {"type": Dscp}, + "monitor": {"type": Monitor}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + profile: str | None + """ + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + """ + mlag: bool + """ + Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be + configured on the MLAG peer-link port-channel. + + Default value: `False` + """ + domain: int + """Default value: `127`""" + priority1: int | None + """default -> automatically set based on node_type.""" + priority2: int | None + """default -> (node_id modulus 256).""" + auto_clock_identity: bool | None + """ + If you prefer to have PTP clock identity be the system MAC-address of the switch, which is the + default EOS behaviour, simply disable the automatic PTP clock identity. + default -> + (clock_identity_prefix = 00:1C:73 (default)) + (PTP priority 1 as HEX) + ":00:" + (PTP priority 2 as + HEX). + """ + clock_identity_prefix: str + """ + PTP clock idetentiy 3-byte prefix. i.e. "01:02:03". + By default the 3-byte prefix is "00:1C:73". + This + can be overridden if auto_clock_identity is set to true (which is the default). + + Default value: `"00:1C:73"` + """ + clock_identity: str | None + """Set PTP clock identity manually. 6-byte value i.e. "01:02:03:04:05:06".""" + source_ip: str | None + """ + By default in EOS, PTP packets are sourced with an IP address from the routed port or from the + relevant SVI, which is the recommended behaviour. + This can be set manually if required, for example, + to a value of "10.1.2.3". + """ + mode: Literal["boundary"] + """Default value: `"boundary"`""" + mode_one_step: bool + """Default value: `False`""" + ttl: int | None + forward_unicast: bool + """ + Enable PTP unicast forwarding. + + Default value: `False` + """ + dscp: Dscp + """Subclass of AvdModel.""" + monitor: Monitor + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + profile: str | None | UndefinedType = Undefined, + mlag: bool | UndefinedType = Undefined, + domain: int | UndefinedType = Undefined, + priority1: int | None | UndefinedType = Undefined, + priority2: int | None | UndefinedType = Undefined, + auto_clock_identity: bool | None | UndefinedType = Undefined, + clock_identity_prefix: str | UndefinedType = Undefined, + clock_identity: str | None | UndefinedType = Undefined, + source_ip: str | None | UndefinedType = Undefined, + mode: Literal["boundary"] | UndefinedType = Undefined, + mode_one_step: bool | UndefinedType = Undefined, + ttl: int | None | UndefinedType = Undefined, + forward_unicast: bool | UndefinedType = Undefined, + dscp: Dscp | UndefinedType = Undefined, + monitor: Monitor | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ptp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + profile: + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + mlag: + Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be + configured on the MLAG peer-link port-channel. + domain: domain + priority1: default -> automatically set based on node_type. + priority2: default -> (node_id modulus 256). + auto_clock_identity: + If you prefer to have PTP clock identity be the system MAC-address of the switch, which is the + default EOS behaviour, simply disable the automatic PTP clock identity. + default -> + (clock_identity_prefix = 00:1C:73 (default)) + (PTP priority 1 as HEX) + ":00:" + (PTP priority 2 as + HEX). + clock_identity_prefix: + PTP clock idetentiy 3-byte prefix. i.e. "01:02:03". + By default the 3-byte prefix is "00:1C:73". + This + can be overridden if auto_clock_identity is set to true (which is the default). + clock_identity: Set PTP clock identity manually. 6-byte value i.e. "01:02:03:04:05:06". + source_ip: + By default in EOS, PTP packets are sourced with an IP address from the routed port or from the + relevant SVI, which is the recommended behaviour. + This can be set manually if required, for example, + to a value of "10.1.2.3". + mode: mode + mode_one_step: mode_one_step + ttl: ttl + forward_unicast: Enable PTP unicast forwarding. + dscp: Subclass of AvdModel. + monitor: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class WanHa(AvdModel): + """Subclass of AvdModel.""" + + class HaInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + HaInterfaces._item_type = str + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "ipsec": {"type": bool, "default": True}, + "mtu": {"type": int, "default": 9194}, + "ha_interfaces": {"type": HaInterfaces}, + "ha_ipv4_pool": {"type": str}, + "max_ha_interfaces": {"type": int}, + "port_channel_id": {"type": int}, + "use_port_channel_for_direct_ha": {"type": bool, "default": True}, + "flow_tracking": {"type": FlowTracking}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group.""" + ipsec: bool + """ + Enable / Disable IPsec over HA path-group when HA is enabled. + + Default value: `True` + """ + mtu: int + """ + Set MTU on WAN HA interfaces. + + Default value: `9194` + """ + ha_interfaces: HaInterfaces + """ + Local WAN HA interfaces + Overwrite the default behavior which is to pick all the `uplink_interfaces`. + Can be used to filter uplink interfaces when there are multiple uplinks. + Limitations: + Either all + interfaces must be uplinks or all interfaces must not be uplinks. + Only one interface is supported + for non uplinks. + + Subclass of AvdList with `str` items. + """ + ha_ipv4_pool: str | None + """ + IP address pool used for WAN HA connectivity. + IP is derived from the node ID. + Not used for uplink + interfaces. + """ + max_ha_interfaces: int | None + """ + Number of parallel links towards HA switches. + Can be used to reserve IP addresses for future + parallel HA links. + """ + port_channel_id: int | None + """Port-channel ID to use for direct HA.""" + use_port_channel_for_direct_ha: bool + """ + Enable or disable using a port-channel interface for direct HA when there is only one interface. + This feature was introduced in EOS 4.33.0F. + + Default value: `True` + """ + flow_tracking: FlowTracking + """ + Configures flow-tracking on the HA interfaces. Overrides `fabric_flow_tracking.wan_ha_links` + setting. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + ipsec: bool | UndefinedType = Undefined, + mtu: int | UndefinedType = Undefined, + ha_interfaces: HaInterfaces | UndefinedType = Undefined, + ha_ipv4_pool: str | None | UndefinedType = Undefined, + max_ha_interfaces: int | None | UndefinedType = Undefined, + port_channel_id: int | None | UndefinedType = Undefined, + use_port_channel_for_direct_ha: bool | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + WanHa. + + + Subclass of AvdModel. + + Args: + enabled: Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group. + ipsec: Enable / Disable IPsec over HA path-group when HA is enabled. + mtu: Set MTU on WAN HA interfaces. + ha_interfaces: + Local WAN HA interfaces + Overwrite the default behavior which is to pick all the `uplink_interfaces`. + Can be used to filter uplink interfaces when there are multiple uplinks. + Limitations: + Either all + interfaces must be uplinks or all interfaces must not be uplinks. + Only one interface is supported + for non uplinks. + + Subclass of AvdList with `str` items. + ha_ipv4_pool: + IP address pool used for WAN HA connectivity. + IP is derived from the node ID. + Not used for uplink + interfaces. + max_ha_interfaces: + Number of parallel links towards HA switches. + Can be used to reserve IP addresses for future + parallel HA links. + port_channel_id: Port-channel ID to use for direct HA. + use_port_channel_for_direct_ha: + Enable or disable using a port-channel interface for direct HA when there is only one interface. + This feature was introduced in EOS 4.33.0F. + flow_tracking: + Configures flow-tracking on the HA interfaces. Overrides `fabric_flow_tracking.wan_ha_links` + setting. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L3InterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "peer_as": {"type": str}, + "ipv4_prefix_list_in": {"type": str}, + "ipv4_prefix_list_out": {"type": str}, + "_custom_data": {"type": dict}, + } + peer_as: str + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + ipv4_prefix_list_in: str | None + """ + Prefix List Name. Accept routes for only these prefixes from the peer. + Required for wan interfaces. + """ + ipv4_prefix_list_out: str | None + """ + Prefix List Name. Advertise routes for only these prefixes. + If not specified, nothing would be + advertised. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + peer_as: str | UndefinedType = Undefined, + ipv4_prefix_list_in: str | None | UndefinedType = Undefined, + ipv4_prefix_list_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + peer_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + ipv4_prefix_list_in: + Prefix List Name. Accept routes for only these prefixes from the peer. + Required for wan interfaces. + ipv4_prefix_list_out: + Prefix List Name. Advertise routes for only these prefixes. + If not specified, nothing would be + advertised. + _custom_data: _custom_data + + """ + + class StaticRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "_custom_data": {"type": dict}} + prefix: str + """IPv4_network/Mask.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, prefix: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + StaticRoutesItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv4_network/Mask. + _custom_data: _custom_data + + """ + + class StaticRoutes(AvdList[StaticRoutesItem]): + """Subclass of AvdList with `StaticRoutesItem` items.""" + + StaticRoutes._item_type = StaticRoutesItem + + class CvPathfinderInternetExit(AvdModel): + """Subclass of AvdModel.""" + + class PoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "tunnel_interface_numbers": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Internet-exit policy name.""" + tunnel_interface_numbers: str | None + """ + Number range to use for Tunnel interfaces to an internet-exit service provider using this local + interface. + Examples: '1-3' or '100,200,300' + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + tunnel_interface_numbers: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PoliciesItem. + + + Subclass of AvdModel. + + Args: + name: Internet-exit policy name. + tunnel_interface_numbers: + Number range to use for Tunnel interfaces to an internet-exit service provider using this local + interface. + Examples: '1-3' or '100,200,300' + _custom_data: _custom_data + + """ + + class Policies(AvdIndexedList[str, PoliciesItem]): + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Policies._item_type = PoliciesItem + + _fields: ClassVar[dict] = {"policies": {"type": Policies}, "_custom_data": {"type": dict}} + policies: Policies + """ + List of Internet-exit policies using this interface as exit. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, policies: Policies | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + CvPathfinderInternetExit. + + + Subclass of AvdModel. + + Args: + policies: + List of Internet-exit policies using this interface as exit. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "profile": {"type": str}, + "name": {"type": str}, + "description": {"type": str}, + "ip_address": {"type": str}, + "dhcp_ip": {"type": str}, + "public_ip": {"type": str}, + "encapsulation_dot1q_vlan": {"type": int}, + "dhcp_accept_default_route": {"type": bool, "default": True}, + "enabled": {"type": bool, "default": True}, + "speed": {"type": str}, + "peer": {"type": str}, + "peer_interface": {"type": str}, + "peer_ip": {"type": str}, + "bgp": {"type": Bgp}, + "ipv4_acl_in": {"type": str}, + "ipv4_acl_out": {"type": str}, + "static_routes": {"type": StaticRoutes}, + "qos_profile": {"type": str}, + "wan_carrier": {"type": str}, + "wan_circuit_id": {"type": str}, + "connected_to_pathfinder": {"type": bool, "default": True}, + "cv_pathfinder_internet_exit": {"type": CvPathfinderInternetExit}, + "raw_eos_cli": {"type": str}, + "flow_tracking": {"type": FlowTracking}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + profile: str | None + """L3 interface profile name. Profile defined under `l3_interface_profiles`.""" + name: str + """ + Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. + For a + subinterface, the parent physical interface is automatically created. + """ + description: str | None + """ + Interface description. + If not set a default description will be configured with '[[ + ]]'. + """ + ip_address: str | None + """Node IPv4 address/Mask or 'dhcp'.""" + dhcp_ip: str | None + """ + When the `ip_address` is `dhcp`, this optional field allows to indicate the expected + IPv4 address + (without mask) to be allocated on the interface if known. + This is not rendered in the configuration + but can be used for substitution of 'interface_ip' in the Access-list + set under `ipv4_acl_in` and + `ipv4_acl_out`. + """ + public_ip: str | None + """ + Node IPv4 address (no mask). + + This is used to get the public IP (if known) when the device is behind + NAT. + This is only used for `wan_rr` routers (AutoVPN RRs and Pathfinders) to determine the Public IP + with the following preference: + `wan_route_servers.path_groups.interfaces.ip_address` + -> + `l3_interfaces.public_ip` + -> `l3_interfaces.ip_address` + + The determined Public IP is used + by WAN routers when peering with this interface. + """ + encapsulation_dot1q_vlan: int | None + """ + For subinterfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + """ + dhcp_accept_default_route: bool + """ + Accept a default route from DHCP if `ip_address` is set to `dhcp`. + + Default value: `True` + """ + enabled: bool + """ + Enable or Shutdown the interface. + + Default value: `True` + """ + speed: str | None + """ + Speed should be set in the format `` or `forced ` or `auto + `. + """ + peer: str | None + """The peer device name. Used for description and documentation.""" + peer_interface: str | None + """The peer device interface. Used for description and documentation.""" + peer_ip: str | None + """ + The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true + and `ip` is an IP address. + """ + bgp: Bgp + """ + Enforce IPv4 BGP peering for the peer + + Subclass of AvdModel. + """ + ipv4_acl_in: str | None + """ + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + Required + for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under + `wan_carriers`. + """ + ipv4_acl_out: str | None + """ + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + """ + static_routes: StaticRoutes + """ + Configure IPv4 static routes pointing to `peer_ip`. + + Subclass of AvdList with `StaticRoutesItem` + items. + """ + qos_profile: str | None + """QOS service profile.""" + wan_carrier: str | None + """ + The WAN carrier this interface is connected to. + This is used to infer the path-groups in which this + interface should be configured. + Unless the carrier is marked as 'trusted' under `wan_carriers`, + `ipv4_acl_in` is also required on all WAN interfaces. + """ + wan_circuit_id: str | None + """ + The WAN circuit ID for this interface. + This is not rendered in the configuration but used for WAN + designs. + """ + connected_to_pathfinder: bool + """ + For a WAN interface (`wan_carrier` is set), allow to disable the static tunnel towards Pathfinders. + + Default value: `True` + """ + cv_pathfinder_internet_exit: CvPathfinderInternetExit + """ + PREVIEW: This key is in preview mode + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the interface in the final EOS configuration.""" + flow_tracking: FlowTracking + """ + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + """ + structured_config: StructuredConfig + """ + Custom structured config for the Ethernet interface. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | None | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + dhcp_ip: str | None | UndefinedType = Undefined, + public_ip: str | None | UndefinedType = Undefined, + encapsulation_dot1q_vlan: int | None | UndefinedType = Undefined, + dhcp_accept_default_route: bool | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + speed: str | None | UndefinedType = Undefined, + peer: str | None | UndefinedType = Undefined, + peer_interface: str | None | UndefinedType = Undefined, + peer_ip: str | None | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + ipv4_acl_in: str | None | UndefinedType = Undefined, + ipv4_acl_out: str | None | UndefinedType = Undefined, + static_routes: StaticRoutes | UndefinedType = Undefined, + qos_profile: str | None | UndefinedType = Undefined, + wan_carrier: str | None | UndefinedType = Undefined, + wan_circuit_id: str | None | UndefinedType = Undefined, + connected_to_pathfinder: bool | UndefinedType = Undefined, + cv_pathfinder_internet_exit: CvPathfinderInternetExit | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L3InterfacesItem. + + + Subclass of AvdModel. + + Args: + profile: L3 interface profile name. Profile defined under `l3_interface_profiles`. + name: + Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. + For a + subinterface, the parent physical interface is automatically created. + description: + Interface description. + If not set a default description will be configured with '[[ + ]]'. + ip_address: Node IPv4 address/Mask or 'dhcp'. + dhcp_ip: + When the `ip_address` is `dhcp`, this optional field allows to indicate the expected + IPv4 address + (without mask) to be allocated on the interface if known. + This is not rendered in the configuration + but can be used for substitution of 'interface_ip' in the Access-list + set under `ipv4_acl_in` and + `ipv4_acl_out`. + public_ip: + Node IPv4 address (no mask). + + This is used to get the public IP (if known) when the device is behind + NAT. + This is only used for `wan_rr` routers (AutoVPN RRs and Pathfinders) to determine the Public IP + with the following preference: + `wan_route_servers.path_groups.interfaces.ip_address` + -> + `l3_interfaces.public_ip` + -> `l3_interfaces.ip_address` + + The determined Public IP is used + by WAN routers when peering with this interface. + encapsulation_dot1q_vlan: + For subinterfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + dhcp_accept_default_route: Accept a default route from DHCP if `ip_address` is set to `dhcp`. + enabled: Enable or Shutdown the interface. + speed: + Speed should be set in the format `` or `forced ` or `auto + `. + peer: The peer device name. Used for description and documentation. + peer_interface: The peer device interface. Used for description and documentation. + peer_ip: + The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true + and `ip` is an IP address. + bgp: + Enforce IPv4 BGP peering for the peer + + Subclass of AvdModel. + ipv4_acl_in: + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + Required + for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under + `wan_carriers`. + ipv4_acl_out: + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + static_routes: + Configure IPv4 static routes pointing to `peer_ip`. + + Subclass of AvdList with `StaticRoutesItem` + items. + qos_profile: QOS service profile. + wan_carrier: + The WAN carrier this interface is connected to. + This is used to infer the path-groups in which this + interface should be configured. + Unless the carrier is marked as 'trusted' under `wan_carriers`, + `ipv4_acl_in` is also required on all WAN interfaces. + wan_circuit_id: + The WAN circuit ID for this interface. + This is not rendered in the configuration but used for WAN + designs. + connected_to_pathfinder: For a WAN interface (`wan_carrier` is set), allow to disable the static tunnel towards Pathfinders. + cv_pathfinder_internet_exit: + PREVIEW: This key is in preview mode + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the interface in the final EOS configuration. + flow_tracking: + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + structured_config: + Custom structured config for the Ethernet interface. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): + """Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + L3Interfaces._item_type = L3InterfacesItem + + _fields: ClassVar[dict] = { + "group": {"type": str}, + "nodes": {"type": Nodes}, + "id": {"type": int}, + "platform": {"type": str}, + "mac_address": {"type": str}, + "system_mac_address": {"type": str}, + "serial_number": {"type": str}, + "rack": {"type": str}, + "mgmt_ip": {"type": str}, + "mgmt_gateway": {"type": str}, + "ipv6_mgmt_ip": {"type": str}, + "ipv6_mgmt_gateway": {"type": str}, + "mgmt_interface": {"type": str}, + "link_tracking": {"type": LinkTracking}, + "lacp_port_id_range": {"type": LacpPortIdRange}, + "always_configure_ip_routing": {"type": bool, "default": False}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "uplink_type": {"type": str}, + "uplink_ipv4_pool": {"type": str}, + "uplink_interfaces": {"type": UplinkInterfaces}, + "uplink_switch_interfaces": {"type": UplinkSwitchInterfaces}, + "uplink_switches": {"type": UplinkSwitches}, + "uplink_interface_speed": {"type": str}, + "uplink_switch_interface_speed": {"type": str}, + "uplink_mtu": {"type": int}, + "max_uplink_switches": {"type": int}, + "max_parallel_uplinks": {"type": int, "default": 1}, + "uplink_bfd": {"type": bool, "default": False}, + "uplink_native_vlan": {"type": int}, + "uplink_ptp": {"type": UplinkPtp}, + "uplink_macsec": {"type": UplinkMacsec}, + "uplink_port_channel_id": {"type": int}, + "uplink_switch_port_channel_id": {"type": int}, + "uplink_structured_config": {"type": dict}, + "mlag_port_channel_structured_config": {"type": MlagPortChannelStructuredConfig}, + "mlag_peer_vlan_structured_config": {"type": MlagPeerVlanStructuredConfig}, + "mlag_peer_l3_vlan_structured_config": {"type": MlagPeerL3VlanStructuredConfig}, + "short_esi": {"type": str}, + "isis_system_id_prefix": {"type": str}, + "isis_maximum_paths": {"type": int}, + "is_type": {"type": str}, + "node_sid_base": {"type": int, "default": 0}, + "loopback_ipv4_pool": {"type": str}, + "loopback_ipv4_address": {"type": str}, + "vtep_loopback_ipv4_pool": {"type": str}, + "vtep_loopback_ipv4_address": {"type": str}, + "loopback_ipv4_offset": {"type": int, "default": 0}, + "loopback_ipv6_pool": {"type": str}, + "loopback_ipv6_offset": {"type": int, "default": 0}, + "vtep": {"type": bool}, + "vtep_loopback": {"type": str}, + "bgp_as": {"type": str}, + "bgp_defaults": {"type": BgpDefaults}, + "evpn_role": {"type": str}, + "evpn_route_servers": {"type": EvpnRouteServers}, + "evpn_services_l2_only": {"type": bool, "default": False}, + "filter": {"type": Filter}, + "igmp_snooping_enabled": {"type": bool}, + "evpn_gateway": {"type": EvpnGateway}, + "ipvpn_gateway": {"type": IpvpnGateway}, + "mlag": {"type": bool, "default": True}, + "mlag_dual_primary_detection": {"type": bool, "default": False}, + "mlag_ibgp_origin_incomplete": {"type": bool, "default": True}, + "mlag_interfaces": {"type": MlagInterfaces}, + "mlag_interfaces_speed": {"type": str}, + "mlag_peer_l3_vlan": {"type": int, "default": 4093}, + "mlag_peer_l3_ipv4_pool": {"type": str}, + "mlag_peer_vlan": {"type": int, "default": 4094}, + "mlag_peer_link_allowed_vlans": {"type": str}, + "mlag_peer_address_family": {"type": str, "default": "ipv4"}, + "mlag_peer_ipv4_pool": {"type": str}, + "mlag_peer_ipv6_pool": {"type": str}, + "mlag_port_channel_id": {"type": int}, + "mlag_domain_id": {"type": str}, + "spanning_tree_mode": {"type": str}, + "spanning_tree_priority": {"type": int, "default": 32768}, + "spanning_tree_root_super": {"type": bool, "default": False}, + "virtual_router_mac_address": {"type": str}, + "inband_mgmt_interface": {"type": str}, + "inband_mgmt_vlan": {"type": int, "default": 4092}, + "inband_mgmt_subnet": {"type": str}, + "inband_mgmt_ip": {"type": str}, + "inband_mgmt_gateway": {"type": str}, + "inband_mgmt_ipv6_address": {"type": str}, + "inband_mgmt_ipv6_subnet": {"type": str}, + "inband_mgmt_ipv6_gateway": {"type": str}, + "inband_mgmt_description": {"type": str, "default": "Inband Management"}, + "inband_mgmt_vlan_name": {"type": str, "default": "INBAND_MGMT"}, + "inband_mgmt_vrf": {"type": str, "default": "default"}, + "inband_mgmt_mtu": {"type": int, "default": 1500}, + "inband_ztp": {"type": bool, "default": False}, + "inband_ztp_lacp_fallback_delay": {"type": int, "default": 30}, + "mpls_overlay_role": {"type": str}, + "overlay_address_families": {"type": OverlayAddressFamilies}, + "mpls_route_reflectors": {"type": MplsRouteReflectors}, + "bgp_cluster_id": {"type": str}, + "ptp": {"type": Ptp}, + "wan_role": {"type": str}, + "cv_pathfinder_transit_mode": {"type": str}, + "cv_pathfinder_region": {"type": str}, + "cv_pathfinder_site": {"type": str}, + "wan_ha": {"type": WanHa}, + "dps_mss_ipv4": {"type": str, "default": "auto"}, + "l3_interfaces": {"type": L3Interfaces}, + "data_plane_cpu_allocation_max": {"type": int}, + "flow_tracker_type": {"type": str}, + "_custom_data": {"type": dict}, + } + group: str + """ + The Node Group Name is used for MLAG domain unless set with 'mlag_domain_id'. + The Node Group Name is + also used for peer description on downstream switches' uplinks. + """ + nodes: Nodes + """ + Define variables per node. + + Subclass of AvdIndexedList with `NodesItem` items. Primary key is `name` + (`str`). + """ + id: int | None + """Unique identifier used for IP addressing and other algorithms.""" + platform: str | None + """Arista platform family.""" + mac_address: str | None + """Leverage to document management interface mac address.""" + system_mac_address: str | None + """ + System MAC Address in this following format: "xx:xx:xx:xx:xx:xx". + Set to the same MAC address as + available in "show version" on the device. + "system_mac_address" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + """ + serial_number: str | None + """ + Set to the Serial Number of the device. + Only used for documentation purpose in the fabric + documentation and part of the structured_config. + "serial_number" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + """ + rack: str | None + """Rack that the switch is located in (only used in snmp_settings location).""" + mgmt_ip: str | None + """Node management interface IPv4 address.""" + mgmt_gateway: str | None + """ + This key sets the management gateway for the device. It takes precedence over the global + `mgmt_gateway`. + """ + ipv6_mgmt_ip: str | None + """Node management interface IPv6 address.""" + ipv6_mgmt_gateway: str | None + """ + This key sets the ipv6 management gateway for the device. It takes precedence over the global + `ipv6_mgmt_gateway`. + """ + mgmt_interface: str | None + """ + Management Interface Name. + Default -> platform_management_interface -> mgmt_interface -> + "Management1". + """ + link_tracking: LinkTracking + """ + This configures the Link Tracking Group on a switch as well as adds the p2p-uplinks of the switch as + the upstream interfaces. + Useful in EVPN multhoming designs. + + + Subclass of AvdModel. + """ + lacp_port_id_range: LacpPortIdRange + """ + This will generate the "lacp port-id range", "begin" and "end" values based on node "id" and the + number of nodes in the "node_group". + Unique LACP port-id ranges are recommended for EVPN Multihoming + designs. + + + Subclass of AvdModel. + """ + always_configure_ip_routing: bool + """ + Force configuration of "ip routing" even on L2 devices. + Use this to retain behavior of AVD versions + below 4.0.0. + + Default value: `False` + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the root level of the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + """ + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None + """ + Override the default `uplink_type` set at the `node_type_key` level. + `uplink_type` must be "p2p" if + `vtep` or `underlay_router` is true for the `node_type_key` definition. + """ + uplink_ipv4_pool: str | None + """IPv4 subnet to use to connect to uplink switches.""" + uplink_interfaces: UplinkInterfaces + """ + Local uplink interfaces. + Each list item supports range syntax that can be expanded into a list of + interfaces. + If uplink_interfaces is not defined, platform-specific defaults (defined under + default_interfaces) will be used instead. + Please note that default_interfaces are not defined by + default, you should define these yourself. + + + Subclass of AvdList with `str` items. + """ + uplink_switch_interfaces: UplinkSwitchInterfaces + """ + Interfaces located on uplink switches. + + Subclass of AvdList with `str` items. + """ + uplink_switches: UplinkSwitches + """Subclass of AvdList with `str` items.""" + uplink_interface_speed: str | None + """ + Set point-to-Point interface speed and will apply to uplink interfaces on both ends. + (Uplink switch + interface speed can be overridden with `uplink_switch_interface_speed`). + Speed should be set in the + format `` or `forced ` or `auto `. + """ + uplink_switch_interface_speed: str | None + """ + 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: int | None + """Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting.""" + max_uplink_switches: int | None + """ + 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: 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 + """ + Enable bfd on uplink interfaces. + + Default value: `False` + """ + uplink_native_vlan: int | None + """ + 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: UplinkPtp + """ + Enable PTP on all infrastructure links. + + Subclass of AvdModel. + """ + uplink_macsec: UplinkMacsec + """ + Enable MacSec on all uplinks. + + Subclass of AvdModel. + """ + uplink_port_channel_id: int | None + """ + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink Port-channel + ID will be set to the number of the lowest member interface defined under `uplink_interfaces`. + For + example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ Eth11/1, Eth22/1 ] -> ID 111 + For + MLAG port-channels ID will be based on the lowest member interface on the first MLAG switch. + This + option overrides the default behavior and statically sets the local Port-channel ID. + Note! Make sure + the ID is unique and does not overlap with autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between 1 and 2000 and both MLAG switches must have the same + value. + """ + uplink_switch_port_channel_id: int | None + """ + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink switch Port- + channel ID will be set to the number of the first interface defined under + `uplink_switch_interfaces`. + For example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ + Eth11/1, Eth22/1 ] -> ID 111 + For MLAG port-channels ID will be based on the lowest member interface + on the first MLAG switch. + This option overrides the default behavior and statically sets the Port- + channel ID on the uplink switch. + Note! Make sure the ID is unique and does not overlap with + autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between + 1 and 2000 and both MLAG switches must have the same value. + """ + uplink_structured_config: dict + """ + Custom structured config applied to "uplink_interfaces", and "uplink_switch_interfaces". + When + uplink_type == "p2p", custom structured config added under ethernet_interfaces.[name=] + for eos_cli_config_gen overrides the settings on the ethernet interface level. + When uplink_type == + "port-channel", custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen overrides the settings on the port-channel interface level. + "uplink_structured_config" is applied after "structured_config", so it can override + "structured_config" defined on node-level. + Note! The content of this dictionary is _not_ validated + by the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + """ + mlag_port_channel_structured_config: MlagPortChannelStructuredConfig + """ + Custom structured config applied to MLAG peer link port-channel id. + Added under + port_channel_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the + port-channel interface level. + "mlag_port_channel_structured_config" is applied after + "structured_config", so it can override "structured_config" defined on node-level. + + + Subclass of + AvdModel. + """ + mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig + """ + Custom structured config applied to MLAG Peer Link (control link) SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_vlan_structured_config" is applied after "structured_config", so it can + override "structured_config" defined on node-level. + + + Subclass of AvdModel. + """ + mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig + """ + Custom structured config applied to MLAG underlay L3 peering SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_l3_vlan_structured_config" is applied after "structured_config", so it + can override "structured_config" defined on node-level. + + + Subclass of AvdModel. + """ + short_esi: str | None + """ + short_esi only valid for l2leaf devices using port-channel uplink. + Setting short_esi to "auto" + generates the short_esi automatically using a hash of configuration elements. + < 0000:0000:0000 | + auto >. + """ + isis_system_id_prefix: str | None + """(4.4 hexadecimal).""" + isis_maximum_paths: int | None + """Number of path to configure in ECMP for ISIS.""" + is_type: Literal["level-1-2", "level-1", "level-2"] | None + """Overrides `isis_default_is_type`.""" + node_sid_base: int + """ + Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID. + + Default value: `0` + """ + loopback_ipv4_pool: str | None + """IPv4 subnet for Loopback0 allocation.""" + loopback_ipv4_address: str | None + """ + IPv4 address without mask for Loopback0. + When set, it takes precedence over `loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not catch duplicates. + """ + vtep_loopback_ipv4_pool: str | None + """IPv4 subnet for VTEP-Loopback allocation.""" + vtep_loopback_ipv4_address: str | None + """ + IPv4 address without mask for VTEP-Loopback. + When set, it takes precedence over + `vtep_loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not + catch duplicates. + """ + loopback_ipv4_offset: int + """ + Offset all assigned loopback IP addresses. + Required when the < loopback_ipv4_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid over-lapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv4_offset: < total # spine switches > or vice versa. + + Default value: `0` + """ + loopback_ipv6_pool: str | None + """IPv6 subnet for Loopback0 allocation.""" + loopback_ipv6_offset: int + """ + Offset all assigned loopback IPv6 addresses. + Required when the < loopback_ipv6_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid overlapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv6_offset: < total # spine switches > or vice versa. + + Default value: `0` + """ + vtep: bool | None + """ + Node is configured as a VTEP when applicable based on 'overlay_routing_protocol'. + Overrides VTEP + setting inherited from node_type_keys. + """ + vtep_loopback: str | None + """Set VXLAN source interface.""" + bgp_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + Required with eBGP. + """ + bgp_defaults: BgpDefaults + """ + List of EOS commands to apply to BGP daemon. + + Subclass of AvdList with `str` items. + """ + evpn_role: Literal["client", "server", "none"] | None + """ + Acting role in EVPN control plane. + Default is set in node_type definition from node_type_keys. + """ + evpn_route_servers: EvpnRouteServers + """ + List of nodes acting as EVPN Route-Servers / Route-Reflectors. + + Subclass of AvdList with `str` + items. + """ + evpn_services_l2_only: bool + """ + Possibility to prevent configuration of Tenant VRFs and SVIs. + Override node definition + "network_services_l3" from node_type_keys. + This allows support for centralized routing. + + Default value: `False` + """ + filter: Filter + """ + Filter L3 and L2 network services based on tenant and tags (and operation filter). + If filter is not + defined it will default to all. + + + Subclass of AvdModel. + """ + igmp_snooping_enabled: bool | None + """Activate or deactivate IGMP snooping on device level.""" + evpn_gateway: EvpnGateway + """ + Node is acting as EVPN Multi-Domain Gateway. + New BGP peer-group is generated between EVPN GWs in + different domains or between GWs and Route Servers. + Name can be changed under + "bgp_peer_groups.evpn_overlay_core" variable. + L3 rechability for different EVPN GWs must be already + in place, it is recommended to use DCI & L3 Edge if Route Servers and GWs are not defined under the + same Ansible inventory. + + + Subclass of AvdModel. + """ + ipvpn_gateway: IpvpnGateway + """ + Node is acting as IP-VPN Gateway for EVPN to MPLS-IP-VPN Interworking. The BGP peer group used for + this is "bgp_peer_groups.ipvpn_gateway_peers". + L3 Reachability is required for this to work, the + preferred method to establish underlay connectivity is to use core_interfaces. + + + Subclass of + AvdModel. + """ + mlag: bool + """ + Enable / Disable auto MLAG, when two nodes are defined in node group. + + Default value: `True` + """ + mlag_dual_primary_detection: bool + """ + Enable / Disable MLAG dual primary detection. + + Default value: `False` + """ + mlag_ibgp_origin_incomplete: bool + """ + Set origin of routes received from MLAG iBGP peer to incomplete. + The purpose is to optimize routing + for leaf loopbacks from spine perspective and + avoid suboptimal routing via peerlink for control + plane traffic. + + Default value: `True` + """ + mlag_interfaces: MlagInterfaces + """ + Each list item supports range syntax that can be expanded into a list of interfaces. + Required when + MLAG leafs are present in the topology. + + + Subclass of AvdList with `str` items. + """ + mlag_interfaces_speed: str | None + """ + Set MLAG interface speed. + Speed should be set in the format `` or `forced + ` or `auto `. + """ + mlag_peer_l3_vlan: int + """ + Underlay L3 peering SVI interface id. + If set to 0 or the same vlan as mlag_peer_vlan, the + mlag_peer_vlan will be used for L3 peering. + + Default value: `4093` + """ + mlag_peer_l3_ipv4_pool: str | None + """ + IP address pool used for MLAG underlay L3 peering. IP is derived from the node id. + Required when + MLAG leafs present in topology and they are using a separate L3 peering VLAN. + """ + mlag_peer_vlan: int + """ + MLAG Peer Link (control link) SVI interface id. + + Default value: `4094` + """ + mlag_peer_link_allowed_vlans: str | None + mlag_peer_address_family: Literal["ipv4", "ipv6"] + """ + IP address family used to establish MLAG Peer Link (control link). + `ipv6` requires EOS version + 4.31.1F or higher. + Note: `ipv6` is not supported in combination with a common MLAG peer link VLAN + (ex. `mlag_peer_l3_vlan` set to 4094). + + Default value: `"ipv4"` + """ + mlag_peer_ipv4_pool: str | None + """ + IPv4 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv4` (default). + """ + mlag_peer_ipv6_pool: str | None + """ + IPv6 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv6`. + """ + mlag_port_channel_id: int | None + """ + If not set, the mlag port-channel id is generated based on the digits of the first interface present + in 'mlag_interfaces'. + Valid port-channel id numbers are < 1-2000 > for EOS < 4.25.0F and < 1 - + 999999 > for EOS >= 4.25.0F. + """ + mlag_domain_id: str | None + """MLAG Domain ID. If not set the node group name (Set with "group" key) will be used.""" + spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None + spanning_tree_priority: int + """ + Spanning-tree priority configured for the selected mode. + For `rapid-pvst` the priority can also be + set per VLAN under network services. + + Default value: `32768` + """ + spanning_tree_root_super: bool + """Default value: `False`""" + virtual_router_mac_address: str | None + """Virtual router mac address for anycast gateway.""" + inband_mgmt_interface: str | None + """ + Pointer to interface used for inband management. + All configuration must be done using other data + models like network services or structured_config. + 'inband_mgmt_interface' is only used to refer to + this interface as source in various management protocol settings (future feature). + + On L2 switches, + this defaults to Vlan if either 'inband_mgmt_subnet' or 'inband_mgmt_ip' is set. + """ + inband_mgmt_vlan: int + """ + VLAN number used for inband management on L2 switches (switches using port-channel trunks as + uplinks). + When using 'inband_mgmt_subnet' the VLAN and SVIs will be created automatically on this + switch as well as all 'uplink_switches'. + When using 'inband_mgmt_ip' the VLAN and SVI will only be + created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be + created using network services data models. + + Default value: `4092` + """ + inband_mgmt_subnet: str | None + """ + Optional IP subnet assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ip virtual-router" and host-route injection based on + ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + + 3 + + GW on l2leafs : + 1 + Assign range larger than total l2leafs + 5 + Setting is ignored if 'inband_mgmt_ip' is set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + """ + inband_mgmt_ip: str | None + """ + IP address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_subnet', hence all behavior of 'inband_mgmt_subnet' is removed. + + If this is set the + VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN and SVI on + the parent switches must be created using network services data models. + + This setting is applicable + to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_gateway: str | None + """ + Default gateway configured in the 'inband_mgmt_vrf' when using 'inband_mgmt_ip'. Otherwise gateway + is derived from 'inband_mgmt_subnet' if set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_address: str | None + """ + IPv6 address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_ipv6_subnet', hence the configuration of 'inband_mgmt_ipv6_subnet' is ignored. + + If this + is set the VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN + and SVI on the parent switches must be created using network services data models. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_subnet: str | None + """ + Optional IPv6 prefix assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ipv6 virtual-router" and host-route injection based + on ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN + extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + 3 + + GW on l2leafs : + 1 + Assign range larger than + total l2leafs + 5 + + Setting is ignored if 'inband_mgmt_ipv6_address' is set. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_gateway: str | None + """ + Default gateway configured in the 'inband_mgmt_vrf'. + Used when `inband_mgmt_ipv6_address` is set. + Ignored when 'inband_mgmt_ipv6_subnet' is set (first IP in subnet used as gateway). + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_description: str + """ + Description configured on the Inband Management SVI. + + This setting is only applied on the devices + where it is set, it does not automatically affect any parent/child devices configuration, so it must + be set on each applicable node/node-group/node-type as needed. + + Default value: `"Inband Management"` + """ + inband_mgmt_vlan_name: str + """ + Name configured on the Inband Management VLAN. + This setting is only applied on the devices where it + is set, it does not automatically affect any parent/child devices configuration, so it must be set + on each applicable node/node-group/node-type as needed. + + Default value: `"INBAND_MGMT"` + """ + inband_mgmt_vrf: str + """ + VRF configured on the Inband Management Interface. + The VRF is created if not already created by + other means. + This setting is only applied on the devices where it is set, it does not automatically + affect any parent/child devices configuration, so it must be set on each applicable node/node- + group/node-type as needed. + + Default value: `"default"` + """ + inband_mgmt_mtu: int + """ + MTU configured on the Inband Management Interface. + This setting is only applied on the devices where + it is set, it does not automatically affect any parent/child devices configuration, so it must be + set on each applicable node/node-group/node-type as needed. + + Default value: `1500` + """ + inband_ztp: bool + """ + Enable to configure upstream device with proper configuration to allow downstream devices to be + Zero-Touch-Provisioned over the uplink interfaces. + For L2 devices this setting also requires that + the `inband_mgmt_vlan` is set for the node. + + PREVIEW: Support for L3 devices is marked as "preview", + meaning the data models or generated configuration can change at any time. + + Default value: `False` + """ + inband_ztp_lacp_fallback_delay: int + """ + Set the LACP fallback timeout of the upstream device's port-channel towards the downstream inband + ZTP node. + This setting also requires that `inband_ztp` is set for the node. + + Default value: `30` + """ + mpls_overlay_role: Literal["client", "server", "none"] | None + """ + Set the default mpls overlay role. + Acting role in overlay control plane. + """ + overlay_address_families: OverlayAddressFamilies + """ + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + """ + mpls_route_reflectors: MplsRouteReflectors + """ + List of inventory hostname acting as MPLS route-reflectors. + + Subclass of AvdList with `str` items. + """ + bgp_cluster_id: str | None + """Set BGP cluster id.""" + ptp: Ptp + """Subclass of AvdModel.""" + wan_role: Literal["client", "server"] | None + """ + Override the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + """ + cv_pathfinder_transit_mode: Literal["region", "zone"] | None + """ + Configure the transit mode for a WAN client for CV Pathfinder designs + only when the `wan_mode` root + key is set to `cv_pathfinder`. + + 'zone' is currently not supported. + """ + cv_pathfinder_region: str | None + """ + The CV Pathfinder region name. + This key is required for WAN routers but optional for pathfinders. + The region name must be defined under 'cv_pathfinder_regions'. + """ + cv_pathfinder_site: str | None + """ + The CV Pathfinder site name. + This key is required for WAN routers but optional for pathfinders. + For + WAN routers and pathfinders with `cv_pathfinder_region`, the site name must be defined for the + relevant region under 'cv_pathfinder_regions'. + For pathfinders without `cv_pathfinder_region` set, + the site must be defined under `cv_pathfinder_global_sites`. + """ + wan_ha: WanHa + """ + PREVIEW: This key is currently not supported + + The key is supported only if `wan_mode` == `cv- + pathfinder`. + AutoVPN support is still to be determined. + + Maximum 2 devices supported by group for + HA. + + Subclass of AvdModel. + """ + dps_mss_ipv4: str + """ + IPv4 MSS value configured under "router path-selection" on WAN Devices. + + Default value: `"auto"` + """ + l3_interfaces: L3Interfaces + """ + L3 Interfaces to configure on the node. + Used to define the node for WAN interfaces when + `wan_carrier` is set. + + Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is + `name` (`str`). + """ + data_plane_cpu_allocation_max: int | None + """ + Set the maximum number of CPU used for the data plane. + This setting is useful on virtual Route + Reflectors and Pathfinders where more CPU cores should be allocated for control plane. + """ + flow_tracker_type: Literal["sampled", "hardware"] | None + """ + Set the flow tracker type. + Override the `default_flow_tracker_type`` set at the `node_type_key` + level. + `default_flow_tracker_type` default value is `sampled`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + group: str | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + id: int | None | UndefinedType = Undefined, + platform: str | None | UndefinedType = Undefined, + mac_address: str | None | UndefinedType = Undefined, + system_mac_address: str | None | UndefinedType = Undefined, + serial_number: str | None | UndefinedType = Undefined, + rack: str | None | UndefinedType = Undefined, + mgmt_ip: str | None | UndefinedType = Undefined, + mgmt_gateway: str | None | UndefinedType = Undefined, + ipv6_mgmt_ip: str | None | UndefinedType = Undefined, + ipv6_mgmt_gateway: str | None | UndefinedType = Undefined, + mgmt_interface: str | None | UndefinedType = Undefined, + link_tracking: LinkTracking | UndefinedType = Undefined, + lacp_port_id_range: LacpPortIdRange | UndefinedType = Undefined, + always_configure_ip_routing: bool | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None | UndefinedType = Undefined, + uplink_ipv4_pool: str | None | UndefinedType = Undefined, + uplink_interfaces: UplinkInterfaces | UndefinedType = Undefined, + uplink_switch_interfaces: UplinkSwitchInterfaces | UndefinedType = Undefined, + uplink_switches: UplinkSwitches | UndefinedType = Undefined, + uplink_interface_speed: str | None | UndefinedType = Undefined, + 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 | UndefinedType = Undefined, + uplink_bfd: bool | UndefinedType = Undefined, + uplink_native_vlan: int | None | UndefinedType = Undefined, + uplink_ptp: UplinkPtp | UndefinedType = Undefined, + uplink_macsec: UplinkMacsec | UndefinedType = Undefined, + uplink_port_channel_id: int | None | UndefinedType = Undefined, + uplink_switch_port_channel_id: int | None | UndefinedType = Undefined, + uplink_structured_config: dict | UndefinedType = Undefined, + mlag_port_channel_structured_config: MlagPortChannelStructuredConfig | UndefinedType = Undefined, + mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig | UndefinedType = Undefined, + mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig | UndefinedType = Undefined, + short_esi: str | None | UndefinedType = Undefined, + isis_system_id_prefix: str | None | UndefinedType = Undefined, + isis_maximum_paths: int | None | UndefinedType = Undefined, + is_type: Literal["level-1-2", "level-1", "level-2"] | None | UndefinedType = Undefined, + node_sid_base: int | UndefinedType = Undefined, + loopback_ipv4_pool: str | None | UndefinedType = Undefined, + loopback_ipv4_address: str | None | UndefinedType = Undefined, + vtep_loopback_ipv4_pool: str | None | UndefinedType = Undefined, + vtep_loopback_ipv4_address: str | None | UndefinedType = Undefined, + loopback_ipv4_offset: int | UndefinedType = Undefined, + loopback_ipv6_pool: str | None | UndefinedType = Undefined, + loopback_ipv6_offset: int | UndefinedType = Undefined, + vtep: bool | None | UndefinedType = Undefined, + vtep_loopback: str | None | UndefinedType = Undefined, + bgp_as: str | None | UndefinedType = Undefined, + bgp_defaults: BgpDefaults | UndefinedType = Undefined, + evpn_role: Literal["client", "server", "none"] | None | UndefinedType = Undefined, + evpn_route_servers: EvpnRouteServers | UndefinedType = Undefined, + evpn_services_l2_only: bool | UndefinedType = Undefined, + filter: Filter | UndefinedType = Undefined, + igmp_snooping_enabled: bool | None | UndefinedType = Undefined, + evpn_gateway: EvpnGateway | UndefinedType = Undefined, + ipvpn_gateway: IpvpnGateway | UndefinedType = Undefined, + mlag: bool | UndefinedType = Undefined, + mlag_dual_primary_detection: bool | UndefinedType = Undefined, + mlag_ibgp_origin_incomplete: bool | UndefinedType = Undefined, + mlag_interfaces: MlagInterfaces | UndefinedType = Undefined, + mlag_interfaces_speed: str | None | UndefinedType = Undefined, + mlag_peer_l3_vlan: int | UndefinedType = Undefined, + mlag_peer_l3_ipv4_pool: str | None | UndefinedType = Undefined, + mlag_peer_vlan: int | UndefinedType = Undefined, + mlag_peer_link_allowed_vlans: str | None | UndefinedType = Undefined, + mlag_peer_address_family: Literal["ipv4", "ipv6"] | UndefinedType = Undefined, + mlag_peer_ipv4_pool: str | None | UndefinedType = Undefined, + mlag_peer_ipv6_pool: str | None | UndefinedType = Undefined, + mlag_port_channel_id: int | None | UndefinedType = Undefined, + mlag_domain_id: str | None | UndefinedType = Undefined, + spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None | UndefinedType = Undefined, + spanning_tree_priority: int | UndefinedType = Undefined, + spanning_tree_root_super: bool | UndefinedType = Undefined, + virtual_router_mac_address: str | None | UndefinedType = Undefined, + inband_mgmt_interface: str | None | UndefinedType = Undefined, + inband_mgmt_vlan: int | UndefinedType = Undefined, + inband_mgmt_subnet: str | None | UndefinedType = Undefined, + inband_mgmt_ip: str | None | UndefinedType = Undefined, + inband_mgmt_gateway: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_address: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_subnet: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_gateway: str | None | UndefinedType = Undefined, + inband_mgmt_description: str | UndefinedType = Undefined, + inband_mgmt_vlan_name: str | UndefinedType = Undefined, + inband_mgmt_vrf: str | UndefinedType = Undefined, + inband_mgmt_mtu: int | UndefinedType = Undefined, + inband_ztp: bool | UndefinedType = Undefined, + inband_ztp_lacp_fallback_delay: int | UndefinedType = Undefined, + mpls_overlay_role: Literal["client", "server", "none"] | None | UndefinedType = Undefined, + overlay_address_families: OverlayAddressFamilies | UndefinedType = Undefined, + mpls_route_reflectors: MplsRouteReflectors | UndefinedType = Undefined, + bgp_cluster_id: str | None | UndefinedType = Undefined, + ptp: Ptp | UndefinedType = Undefined, + wan_role: Literal["client", "server"] | None | UndefinedType = Undefined, + cv_pathfinder_transit_mode: Literal["region", "zone"] | None | UndefinedType = Undefined, + cv_pathfinder_region: str | None | UndefinedType = Undefined, + cv_pathfinder_site: str | None | UndefinedType = Undefined, + wan_ha: WanHa | UndefinedType = Undefined, + dps_mss_ipv4: str | UndefinedType = Undefined, + l3_interfaces: L3Interfaces | UndefinedType = Undefined, + data_plane_cpu_allocation_max: int | None | UndefinedType = Undefined, + flow_tracker_type: Literal["sampled", "hardware"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NodeGroupsItem. + + + Subclass of AvdModel. + + Args: + group: + The Node Group Name is used for MLAG domain unless set with 'mlag_domain_id'. + The Node Group Name is + also used for peer description on downstream switches' uplinks. + nodes: + Define variables per node. + + Subclass of AvdIndexedList with `NodesItem` items. Primary key is `name` + (`str`). + id: Unique identifier used for IP addressing and other algorithms. + platform: Arista platform family. + mac_address: Leverage to document management interface mac address. + system_mac_address: + System MAC Address in this following format: "xx:xx:xx:xx:xx:xx". + Set to the same MAC address as + available in "show version" on the device. + "system_mac_address" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + serial_number: + Set to the Serial Number of the device. + Only used for documentation purpose in the fabric + documentation and part of the structured_config. + "serial_number" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + rack: Rack that the switch is located in (only used in snmp_settings location). + mgmt_ip: Node management interface IPv4 address. + mgmt_gateway: + This key sets the management gateway for the device. It takes precedence over the global + `mgmt_gateway`. + ipv6_mgmt_ip: Node management interface IPv6 address. + ipv6_mgmt_gateway: + This key sets the ipv6 management gateway for the device. It takes precedence over the global + `ipv6_mgmt_gateway`. + mgmt_interface: + Management Interface Name. + Default -> platform_management_interface -> mgmt_interface -> + "Management1". + link_tracking: + This configures the Link Tracking Group on a switch as well as adds the p2p-uplinks of the switch as + the upstream interfaces. + Useful in EVPN multhoming designs. + + + Subclass of AvdModel. + lacp_port_id_range: + This will generate the "lacp port-id range", "begin" and "end" values based on node "id" and the + number of nodes in the "node_group". + Unique LACP port-id ranges are recommended for EVPN Multihoming + designs. + + + Subclass of AvdModel. + always_configure_ip_routing: + Force configuration of "ip routing" even on L2 devices. + Use this to retain behavior of AVD versions + below 4.0.0. + raw_eos_cli: EOS CLI rendered directly on the root level of the final EOS configuration. + structured_config: + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + uplink_type: + Override the default `uplink_type` set at the `node_type_key` level. + `uplink_type` must be "p2p" if + `vtep` or `underlay_router` is true for the `node_type_key` definition. + uplink_ipv4_pool: IPv4 subnet to use to connect to uplink switches. + uplink_interfaces: + Local uplink interfaces. + Each list item supports range syntax that can be expanded into a list of + interfaces. + If uplink_interfaces is not defined, platform-specific defaults (defined under + default_interfaces) will be used instead. + Please note that default_interfaces are not defined by + default, you should define these yourself. + + + Subclass of AvdList with `str` items. + uplink_switch_interfaces: + Interfaces located on uplink switches. + + Subclass of AvdList with `str` items. + uplink_switches: Subclass of AvdList with `str` items. + uplink_interface_speed: + Set point-to-Point interface speed and will apply to uplink interfaces on both ends. + (Uplink switch + interface speed can be overridden with `uplink_switch_interface_speed`). + Speed should be set in the + format `` or `forced ` or `auto `. + uplink_switch_interface_speed: + 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: Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting. + max_uplink_switches: + 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: + 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: Enable bfd on uplink interfaces. + uplink_native_vlan: + 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: + Enable PTP on all infrastructure links. + + Subclass of AvdModel. + uplink_macsec: + Enable MacSec on all uplinks. + + Subclass of AvdModel. + uplink_port_channel_id: + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink Port-channel + ID will be set to the number of the lowest member interface defined under `uplink_interfaces`. + For + example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ Eth11/1, Eth22/1 ] -> ID 111 + For + MLAG port-channels ID will be based on the lowest member interface on the first MLAG switch. + This + option overrides the default behavior and statically sets the local Port-channel ID. + Note! Make sure + the ID is unique and does not overlap with autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between 1 and 2000 and both MLAG switches must have the same + value. + uplink_switch_port_channel_id: + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink switch Port- + channel ID will be set to the number of the first interface defined under + `uplink_switch_interfaces`. + For example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ + Eth11/1, Eth22/1 ] -> ID 111 + For MLAG port-channels ID will be based on the lowest member interface + on the first MLAG switch. + This option overrides the default behavior and statically sets the Port- + channel ID on the uplink switch. + Note! Make sure the ID is unique and does not overlap with + autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between + 1 and 2000 and both MLAG switches must have the same value. + uplink_structured_config: + Custom structured config applied to "uplink_interfaces", and "uplink_switch_interfaces". + When + uplink_type == "p2p", custom structured config added under ethernet_interfaces.[name=] + for eos_cli_config_gen overrides the settings on the ethernet interface level. + When uplink_type == + "port-channel", custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen overrides the settings on the port-channel interface level. + "uplink_structured_config" is applied after "structured_config", so it can override + "structured_config" defined on node-level. + Note! The content of this dictionary is _not_ validated + by the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + mlag_port_channel_structured_config: + Custom structured config applied to MLAG peer link port-channel id. + Added under + port_channel_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the + port-channel interface level. + "mlag_port_channel_structured_config" is applied after + "structured_config", so it can override "structured_config" defined on node-level. + + + Subclass of + AvdModel. + mlag_peer_vlan_structured_config: + Custom structured config applied to MLAG Peer Link (control link) SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_vlan_structured_config" is applied after "structured_config", so it can + override "structured_config" defined on node-level. + + + Subclass of AvdModel. + mlag_peer_l3_vlan_structured_config: + Custom structured config applied to MLAG underlay L3 peering SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_l3_vlan_structured_config" is applied after "structured_config", so it + can override "structured_config" defined on node-level. + + + Subclass of AvdModel. + short_esi: + short_esi only valid for l2leaf devices using port-channel uplink. + Setting short_esi to "auto" + generates the short_esi automatically using a hash of configuration elements. + < 0000:0000:0000 | + auto >. + isis_system_id_prefix: (4.4 hexadecimal). + isis_maximum_paths: Number of path to configure in ECMP for ISIS. + is_type: Overrides `isis_default_is_type`. + node_sid_base: Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID. + loopback_ipv4_pool: IPv4 subnet for Loopback0 allocation. + loopback_ipv4_address: + IPv4 address without mask for Loopback0. + When set, it takes precedence over `loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not catch duplicates. + vtep_loopback_ipv4_pool: IPv4 subnet for VTEP-Loopback allocation. + vtep_loopback_ipv4_address: + IPv4 address without mask for VTEP-Loopback. + When set, it takes precedence over + `vtep_loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not + catch duplicates. + loopback_ipv4_offset: + Offset all assigned loopback IP addresses. + Required when the < loopback_ipv4_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid over-lapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv4_offset: < total # spine switches > or vice versa. + loopback_ipv6_pool: IPv6 subnet for Loopback0 allocation. + loopback_ipv6_offset: + Offset all assigned loopback IPv6 addresses. + Required when the < loopback_ipv6_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid overlapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv6_offset: < total # spine switches > or vice versa. + vtep: + Node is configured as a VTEP when applicable based on 'overlay_routing_protocol'. + Overrides VTEP + setting inherited from node_type_keys. + vtep_loopback: Set VXLAN source interface. + bgp_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + Required with eBGP. + bgp_defaults: + List of EOS commands to apply to BGP daemon. + + Subclass of AvdList with `str` items. + evpn_role: + Acting role in EVPN control plane. + Default is set in node_type definition from node_type_keys. + evpn_route_servers: + List of nodes acting as EVPN Route-Servers / Route-Reflectors. + + Subclass of AvdList with `str` + items. + evpn_services_l2_only: + Possibility to prevent configuration of Tenant VRFs and SVIs. + Override node definition + "network_services_l3" from node_type_keys. + This allows support for centralized routing. + filter: + Filter L3 and L2 network services based on tenant and tags (and operation filter). + If filter is not + defined it will default to all. + + + Subclass of AvdModel. + igmp_snooping_enabled: Activate or deactivate IGMP snooping on device level. + evpn_gateway: + Node is acting as EVPN Multi-Domain Gateway. + New BGP peer-group is generated between EVPN GWs in + different domains or between GWs and Route Servers. + Name can be changed under + "bgp_peer_groups.evpn_overlay_core" variable. + L3 rechability for different EVPN GWs must be already + in place, it is recommended to use DCI & L3 Edge if Route Servers and GWs are not defined under the + same Ansible inventory. + + + Subclass of AvdModel. + ipvpn_gateway: + Node is acting as IP-VPN Gateway for EVPN to MPLS-IP-VPN Interworking. The BGP peer group used for + this is "bgp_peer_groups.ipvpn_gateway_peers". + L3 Reachability is required for this to work, the + preferred method to establish underlay connectivity is to use core_interfaces. + + + Subclass of + AvdModel. + mlag: Enable / Disable auto MLAG, when two nodes are defined in node group. + mlag_dual_primary_detection: Enable / Disable MLAG dual primary detection. + mlag_ibgp_origin_incomplete: + Set origin of routes received from MLAG iBGP peer to incomplete. + The purpose is to optimize routing + for leaf loopbacks from spine perspective and + avoid suboptimal routing via peerlink for control + plane traffic. + mlag_interfaces: + Each list item supports range syntax that can be expanded into a list of interfaces. + Required when + MLAG leafs are present in the topology. + + + Subclass of AvdList with `str` items. + mlag_interfaces_speed: + Set MLAG interface speed. + Speed should be set in the format `` or `forced + ` or `auto `. + mlag_peer_l3_vlan: + Underlay L3 peering SVI interface id. + If set to 0 or the same vlan as mlag_peer_vlan, the + mlag_peer_vlan will be used for L3 peering. + mlag_peer_l3_ipv4_pool: + IP address pool used for MLAG underlay L3 peering. IP is derived from the node id. + Required when + MLAG leafs present in topology and they are using a separate L3 peering VLAN. + mlag_peer_vlan: MLAG Peer Link (control link) SVI interface id. + mlag_peer_link_allowed_vlans: mlag_peer_link_allowed_vlans + mlag_peer_address_family: + IP address family used to establish MLAG Peer Link (control link). + `ipv6` requires EOS version + 4.31.1F or higher. + Note: `ipv6` is not supported in combination with a common MLAG peer link VLAN + (ex. `mlag_peer_l3_vlan` set to 4094). + mlag_peer_ipv4_pool: + IPv4 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv4` (default). + mlag_peer_ipv6_pool: + IPv6 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv6`. + mlag_port_channel_id: + If not set, the mlag port-channel id is generated based on the digits of the first interface present + in 'mlag_interfaces'. + Valid port-channel id numbers are < 1-2000 > for EOS < 4.25.0F and < 1 - + 999999 > for EOS >= 4.25.0F. + mlag_domain_id: MLAG Domain ID. If not set the node group name (Set with "group" key) will be used. + spanning_tree_mode: spanning_tree_mode + spanning_tree_priority: + Spanning-tree priority configured for the selected mode. + For `rapid-pvst` the priority can also be + set per VLAN under network services. + spanning_tree_root_super: spanning_tree_root_super + virtual_router_mac_address: Virtual router mac address for anycast gateway. + inband_mgmt_interface: + Pointer to interface used for inband management. + All configuration must be done using other data + models like network services or structured_config. + 'inband_mgmt_interface' is only used to refer to + this interface as source in various management protocol settings (future feature). + + On L2 switches, + this defaults to Vlan if either 'inband_mgmt_subnet' or 'inband_mgmt_ip' is set. + inband_mgmt_vlan: + VLAN number used for inband management on L2 switches (switches using port-channel trunks as + uplinks). + When using 'inband_mgmt_subnet' the VLAN and SVIs will be created automatically on this + switch as well as all 'uplink_switches'. + When using 'inband_mgmt_ip' the VLAN and SVI will only be + created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be + created using network services data models. + inband_mgmt_subnet: + Optional IP subnet assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ip virtual-router" and host-route injection based on + ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + + 3 + + GW on l2leafs : + 1 + Assign range larger than total l2leafs + 5 + Setting is ignored if 'inband_mgmt_ip' is set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + inband_mgmt_ip: + IP address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_subnet', hence all behavior of 'inband_mgmt_subnet' is removed. + + If this is set the + VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN and SVI on + the parent switches must be created using network services data models. + + This setting is applicable + to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_gateway: + Default gateway configured in the 'inband_mgmt_vrf' when using 'inband_mgmt_ip'. Otherwise gateway + is derived from 'inband_mgmt_subnet' if set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + inband_mgmt_ipv6_address: + IPv6 address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_ipv6_subnet', hence the configuration of 'inband_mgmt_ipv6_subnet' is ignored. + + If this + is set the VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN + and SVI on the parent switches must be created using network services data models. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_ipv6_subnet: + Optional IPv6 prefix assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ipv6 virtual-router" and host-route injection based + on ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN + extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + 3 + + GW on l2leafs : + 1 + Assign range larger than + total l2leafs + 5 + + Setting is ignored if 'inband_mgmt_ipv6_address' is set. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_ipv6_gateway: + Default gateway configured in the 'inband_mgmt_vrf'. + Used when `inband_mgmt_ipv6_address` is set. + Ignored when 'inband_mgmt_ipv6_subnet' is set (first IP in subnet used as gateway). + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_description: + Description configured on the Inband Management SVI. + + This setting is only applied on the devices + where it is set, it does not automatically affect any parent/child devices configuration, so it must + be set on each applicable node/node-group/node-type as needed. + inband_mgmt_vlan_name: + Name configured on the Inband Management VLAN. + This setting is only applied on the devices where it + is set, it does not automatically affect any parent/child devices configuration, so it must be set + on each applicable node/node-group/node-type as needed. + inband_mgmt_vrf: + VRF configured on the Inband Management Interface. + The VRF is created if not already created by + other means. + This setting is only applied on the devices where it is set, it does not automatically + affect any parent/child devices configuration, so it must be set on each applicable node/node- + group/node-type as needed. + inband_mgmt_mtu: + MTU configured on the Inband Management Interface. + This setting is only applied on the devices where + it is set, it does not automatically affect any parent/child devices configuration, so it must be + set on each applicable node/node-group/node-type as needed. + inband_ztp: + Enable to configure upstream device with proper configuration to allow downstream devices to be + Zero-Touch-Provisioned over the uplink interfaces. + For L2 devices this setting also requires that + the `inband_mgmt_vlan` is set for the node. + + PREVIEW: Support for L3 devices is marked as "preview", + meaning the data models or generated configuration can change at any time. + inband_ztp_lacp_fallback_delay: + Set the LACP fallback timeout of the upstream device's port-channel towards the downstream inband + ZTP node. + This setting also requires that `inband_ztp` is set for the node. + mpls_overlay_role: + Set the default mpls overlay role. + Acting role in overlay control plane. + overlay_address_families: + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + mpls_route_reflectors: + List of inventory hostname acting as MPLS route-reflectors. + + Subclass of AvdList with `str` items. + bgp_cluster_id: Set BGP cluster id. + ptp: Subclass of AvdModel. + wan_role: + Override the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + cv_pathfinder_transit_mode: + Configure the transit mode for a WAN client for CV Pathfinder designs + only when the `wan_mode` root + key is set to `cv_pathfinder`. + + 'zone' is currently not supported. + cv_pathfinder_region: + The CV Pathfinder region name. + This key is required for WAN routers but optional for pathfinders. + The region name must be defined under 'cv_pathfinder_regions'. + cv_pathfinder_site: + The CV Pathfinder site name. + This key is required for WAN routers but optional for pathfinders. + For + WAN routers and pathfinders with `cv_pathfinder_region`, the site name must be defined for the + relevant region under 'cv_pathfinder_regions'. + For pathfinders without `cv_pathfinder_region` set, + the site must be defined under `cv_pathfinder_global_sites`. + wan_ha: + PREVIEW: This key is currently not supported + + The key is supported only if `wan_mode` == `cv- + pathfinder`. + AutoVPN support is still to be determined. + + Maximum 2 devices supported by group for + HA. + + Subclass of AvdModel. + dps_mss_ipv4: IPv4 MSS value configured under "router path-selection" on WAN Devices. + l3_interfaces: + L3 Interfaces to configure on the node. + Used to define the node for WAN interfaces when + `wan_carrier` is set. + + Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is + `name` (`str`). + data_plane_cpu_allocation_max: + Set the maximum number of CPU used for the data plane. + This setting is useful on virtual Route + Reflectors and Pathfinders where more CPU cores should be allocated for control plane. + flow_tracker_type: + Set the flow tracker type. + Override the `default_flow_tracker_type`` set at the `node_type_key` + level. + `default_flow_tracker_type` default value is `sampled`. + _custom_data: _custom_data + + """ + + class NodeGroups(AvdIndexedList[str, NodeGroupsItem]): + """Subclass of AvdIndexedList with `NodeGroupsItem` items. Primary key is `group` (`str`).""" + + _primary_key: ClassVar[str] = "group" + + NodeGroups._item_type = NodeGroupsItem + + class NodesItem(AvdModel): + """Subclass of AvdModel.""" + + class DownlinkPoolsItem(AvdModel): + """Subclass of AvdModel.""" + + class DownlinkInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DownlinkInterfaces._item_type = str + + _fields: ClassVar[dict] = { + "ipv4_pool": {"type": str}, + "downlink_interfaces": {"type": DownlinkInterfaces}, + "_custom_data": {"type": dict}, + } + ipv4_pool: str | None + """IPv4 pool from which subnets will be allocated for links to downlink switches.""" + downlink_interfaces: DownlinkInterfaces + """ + List of downlink interfaces or ranges of interfaces to use this pool. The index of the interface in + this list will determine which subnet will be taken from the pool. + + Subclass of AvdList with `str` + items. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + ipv4_pool: str | None | UndefinedType = Undefined, + downlink_interfaces: DownlinkInterfaces | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + DownlinkPoolsItem. + + + Subclass of AvdModel. + + Args: + ipv4_pool: IPv4 pool from which subnets will be allocated for links to downlink switches. + downlink_interfaces: + List of downlink interfaces or ranges of interfaces to use this pool. The index of the interface in + this list will determine which subnet will be taken from the pool. + + Subclass of AvdList with `str` + items. + _custom_data: _custom_data + + """ + + class DownlinkPools(AvdList[DownlinkPoolsItem]): + """Subclass of AvdList with `DownlinkPoolsItem` items.""" + + DownlinkPools._item_type = DownlinkPoolsItem + + class LinkTracking(AvdModel): + """Subclass of AvdModel.""" + + class GroupsItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "recovery_delay": {"type": int}, + "links_minimum": {"type": int}, + "_custom_data": {"type": dict}, + } + name: str | None + """Tracking group name.""" + recovery_delay: int | None + """default -> platform_settings_mlag_reload_delay -> 300.""" + links_minimum: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | None | UndefinedType = Undefined, + recovery_delay: int | None | UndefinedType = Undefined, + links_minimum: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + GroupsItem. + + + Subclass of AvdModel. + + Args: + name: Tracking group name. + recovery_delay: default -> platform_settings_mlag_reload_delay -> 300. + links_minimum: links_minimum + _custom_data: _custom_data + + """ + + class Groups(AvdList[GroupsItem]): + """Subclass of AvdList with `GroupsItem` items.""" + + Groups._item_type = GroupsItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "groups": {"type": Groups, "default": lambda cls: coerce_type([{"name": "LT_GROUP1"}], target_type=cls)}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + groups: Groups + """ + Link Tracking Groups. + By default a single group named "LT_GROUP1" is defined with default values. + Any groups defined under "groups" will replace the default. + + + Subclass of AvdList with `GroupsItem` + items. + + Default value: `lambda cls: coerce_type([{"name": "LT_GROUP1"}], target_type=cls)` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + groups: Groups | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LinkTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + groups: + Link Tracking Groups. + By default a single group named "LT_GROUP1" is defined with default values. + Any groups defined under "groups" will replace the default. + + + Subclass of AvdList with `GroupsItem` + items. + _custom_data: _custom_data + + """ + + class LacpPortIdRange(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "size": {"type": int, "default": 128}, + "offset": {"type": int, "default": 0}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + size: int + """ + Recommended size > = number of ports in the switch. + + Default value: `128` + """ + offset: int + """ + Offset is used to avoid overlapping port-id ranges of different switches. + Useful when a "connected- + endpoint" is connected to switches in different "node_groups". + + Default value: `0` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + size: int | UndefinedType = Undefined, + offset: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + LacpPortIdRange. + + + Subclass of AvdModel. + + Args: + enabled: enabled + size: Recommended size > = number of ports in the switch. + offset: + Offset is used to avoid overlapping port-id ranges of different switches. + Useful when a "connected- + endpoint" is connected to switches in different "node_groups". + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen): + """Subclass of AvdModel.""" + + class UplinkInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkInterfaces._item_type = str + + class UplinkSwitchInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkSwitchInterfaces._item_type = str + + class UplinkSwitches(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + UplinkSwitches._item_type = str + + class UplinkPtp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enable": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enable: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__(self, *, enable: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined) -> None: + """ + UplinkPtp. + + + Subclass of AvdModel. + + Args: + enable: enable + _custom_data: _custom_data + + """ + + class UplinkMacsec(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"profile": {"type": str}, "_custom_data": {"type": dict}} + profile: str | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, profile: str | None | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + UplinkMacsec. + + + Subclass of AvdModel. + + Args: + profile: profile + _custom_data: _custom_data + + """ + + class MlagPortChannelStructuredConfig(EosCliConfigGen.PortChannelInterfacesItem): + """Subclass of AvdModel.""" + + class MlagPeerVlanStructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + class MlagPeerL3VlanStructuredConfig(EosCliConfigGen.VlanInterfacesItem): + """Subclass of AvdModel.""" + + class BgpDefaults(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + BgpDefaults._item_type = str + + class EvpnRouteServers(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + EvpnRouteServers._item_type = str + + class Filter(AvdModel): + """Subclass of AvdModel.""" + + class Tenants(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tenants._item_type = str + + class Tags(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + Tags._item_type = str + + class AllowVrfs(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AllowVrfs._item_type = str + + class DenyVrfs(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + DenyVrfs._item_type = str + + class AlwaysIncludeVrfsInTenants(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AlwaysIncludeVrfsInTenants._item_type = str + + _fields: ClassVar[dict] = { + "tenants": {"type": Tenants, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "tags": {"type": Tags, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "allow_vrfs": {"type": AllowVrfs, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "deny_vrfs": {"type": DenyVrfs, "default": lambda cls: coerce_type(["all"], target_type=cls)}, + "always_include_vrfs_in_tenants": {"type": AlwaysIncludeVrfsInTenants}, + "only_vlans_in_use": {"type": bool, "default": False}, + "_custom_data": {"type": dict}, + } + tenants: Tenants + """ + Limit configured Network Services to those defined under these Tenants. Set to ['all'] for all + Tenants (default). + This list also limits Tenants included by `always_include_vrfs_in_tenants`. + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + tags: Tags + """ + Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default). + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + allow_vrfs: AllowVrfs + """ + Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs + (default). + This list also limits VRFs included by `always_include_vrfs_in_tenants`. + + Subclass of + AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + deny_vrfs: DenyVrfs + """ + Prevent configuration of Network Services defined under these VRFs. + This list prevents the given + VRFs to be included by any other filtering mechanism. + + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["all"], target_type=cls)` + """ + always_include_vrfs_in_tenants: AlwaysIncludeVrfsInTenants + """ + List of tenants where VRFs will be configured even if VLANs are not included in tags. + Useful for L3 + "border" leaf. + + + Subclass of AvdList with `str` items. + """ + only_vlans_in_use: bool + """ + Only configure VLANs, SVIs, VRFs in use by connected endpoints or downstream L2 switches. + Note! This + feature only considers configuration managed by eos_designs. + This excludes structured_config, + custom_structured_configuration_, raw_eos_cli, eos_cli, custom templates, configlets etc. + + Default value: `False` + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + tenants: Tenants | UndefinedType = Undefined, + tags: Tags | UndefinedType = Undefined, + allow_vrfs: AllowVrfs | UndefinedType = Undefined, + deny_vrfs: DenyVrfs | UndefinedType = Undefined, + always_include_vrfs_in_tenants: AlwaysIncludeVrfsInTenants | UndefinedType = Undefined, + only_vlans_in_use: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Filter. + + + Subclass of AvdModel. + + Args: + tenants: + Limit configured Network Services to those defined under these Tenants. Set to ['all'] for all + Tenants (default). + This list also limits Tenants included by `always_include_vrfs_in_tenants`. + Subclass of AvdList with `str` items. + tags: + Limit configured VLANs to those matching the given tags. Set to ['all'] for all VLANs (default). + Subclass of AvdList with `str` items. + allow_vrfs: + Limit configured Network Services to those defined under these VRFs. Set to ['all'] for all VRFs + (default). + This list also limits VRFs included by `always_include_vrfs_in_tenants`. + + Subclass of + AvdList with `str` items. + deny_vrfs: + Prevent configuration of Network Services defined under these VRFs. + This list prevents the given + VRFs to be included by any other filtering mechanism. + + Subclass of AvdList with `str` items. + always_include_vrfs_in_tenants: + List of tenants where VRFs will be configured even if VLANs are not included in tags. + Useful for L3 + "border" leaf. + + + Subclass of AvdList with `str` items. + only_vlans_in_use: + Only configure VLANs, SVIs, VRFs in use by connected endpoints or downstream L2 switches. + Note! This + feature only considers configuration managed by eos_designs. + This excludes structured_config, + custom_structured_configuration_, raw_eos_cli, eos_cli, custom templates, configlets etc. + _custom_data: _custom_data + + """ + + class EvpnGateway(AvdModel): + """Subclass of AvdModel.""" + + class RemotePeersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hostname": {"type": str}, + "ip_address": {"type": str}, + "bgp_as": {"type": str}, + "_custom_data": {"type": dict}, + } + hostname: str + """Hostname of remote EVPN GW server.""" + ip_address: str | None + """Peering IP of remote Route Server.""" + bgp_as: str | None + """ + Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being + interpreted as a float number. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: str | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + bgp_as: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemotePeersItem. + + + Subclass of AvdModel. + + Args: + hostname: Hostname of remote EVPN GW server. + ip_address: Peering IP of remote Route Server. + bgp_as: + Remote Route Server's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being + interpreted as a float number. + _custom_data: _custom_data + + """ + + class RemotePeers(AvdIndexedList[str, RemotePeersItem]): + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + + _primary_key: ClassVar[str] = "hostname" + + RemotePeers._item_type = RemotePeersItem + + class EvpnL2(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool, "default": False}, "_custom_data": {"type": dict}} + enabled: bool + """Default value: `False`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, enabled: bool | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + EvpnL2. + + + Subclass of AvdModel. + + Args: + enabled: enabled + _custom_data: _custom_data + + """ + + class EvpnL3(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": False}, + "inter_domain": {"type": bool, "default": True}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `False`""" + inter_domain: bool + """Default value: `True`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + inter_domain: bool | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnL3. + + + Subclass of AvdModel. + + Args: + enabled: enabled + inter_domain: inter_domain + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "remote_peers": {"type": RemotePeers}, + "evpn_l2": {"type": EvpnL2}, + "evpn_l3": {"type": EvpnL3}, + "_custom_data": {"type": dict}, + } + remote_peers: RemotePeers + """ + Define remote peers of the EVPN VXLAN Gateway. + If the hostname can be found in the inventory, + ip_address and BGP ASN will be automatically populated. Manual override takes precedence. + If the + peer's hostname can not be found in the inventory, ip_address and bgp_as must be defined. + + + Subclass + of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + """ + evpn_l2: EvpnL2 + """ + Enable EVPN Gateway functionality for route-types 2 (MAC-IP) and 3 (IMET). + + Subclass of AvdModel. + """ + evpn_l3: EvpnL3 + """ + Enable EVPN Gateway functionality for route-type 5 (IP-PREFIX). + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + remote_peers: RemotePeers | UndefinedType = Undefined, + evpn_l2: EvpnL2 | UndefinedType = Undefined, + evpn_l3: EvpnL3 | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + EvpnGateway. + + + Subclass of AvdModel. + + Args: + remote_peers: + Define remote peers of the EVPN VXLAN Gateway. + If the hostname can be found in the inventory, + ip_address and BGP ASN will be automatically populated. Manual override takes precedence. + If the + peer's hostname can not be found in the inventory, ip_address and bgp_as must be defined. + + + Subclass + of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + evpn_l2: + Enable EVPN Gateway functionality for route-types 2 (MAC-IP) and 3 (IMET). + + Subclass of AvdModel. + evpn_l3: + Enable EVPN Gateway functionality for route-type 5 (IP-PREFIX). + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class IpvpnGateway(AvdModel): + """Subclass of AvdModel.""" + + class AddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + AddressFamilies._item_type = str + + class RemotePeersItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "hostname": {"type": str}, + "ip_address": {"type": str}, + "bgp_as": {"type": str}, + "_custom_data": {"type": dict}, + } + hostname: str + """Hostname of remote IPVPN Peer.""" + ip_address: str + """Peering IP of remote IPVPN Peer.""" + bgp_as: str + """ + Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For + asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted + as a float number. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + hostname: str | UndefinedType = Undefined, + ip_address: str | UndefinedType = Undefined, + bgp_as: str | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + RemotePeersItem. + + + Subclass of AvdModel. + + Args: + hostname: Hostname of remote IPVPN Peer. + ip_address: Peering IP of remote IPVPN Peer. + bgp_as: + Remote IPVPN Peer's BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For + asdot notation in YAML inputs, the value must be put in quotes, to prevent it from being interpreted + as a float number. + _custom_data: _custom_data + + """ + + class RemotePeers(AvdIndexedList[str, RemotePeersItem]): + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + + _primary_key: ClassVar[str] = "hostname" + + RemotePeers._item_type = RemotePeersItem + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "evpn_domain_id": {"type": str, "default": "65535:1"}, + "ipvpn_domain_id": {"type": str, "default": "65535:2"}, + "enable_d_path": {"type": bool, "default": True}, + "maximum_routes": {"type": int, "default": 0}, + "local_as": {"type": str}, + "address_families": {"type": AddressFamilies, "default": lambda cls: coerce_type(["vpn-ipv4"], target_type=cls)}, + "remote_peers": {"type": RemotePeers}, + "_custom_data": {"type": dict}, + } + enabled: bool + evpn_domain_id: str + """ + Domain ID to assign to EVPN address family for use with D-path. Format :. + + Default value: `"65535:1"` + """ + ipvpn_domain_id: str + """ + Domain ID to assign to IPVPN address families for use with D-path. Format :. + + Default value: `"65535:2"` + """ + enable_d_path: bool + """ + Enable D-path for use with BGP bestpath selection algorithm. + + Default value: `True` + """ + maximum_routes: int + """ + Maximum routes to accept from IPVPN remote peers. + + Default value: `0` + """ + local_as: str | None + """ + Local BGP AS applied to peering with IPVPN remote peers. + BGP AS <1-4294967295> or AS number in asdot + notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number. + """ + address_families: AddressFamilies + """ + IPVPN address families to enable for remote peers. + + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["vpn-ipv4"], target_type=cls)` + """ + remote_peers: RemotePeers + """Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`).""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + evpn_domain_id: str | UndefinedType = Undefined, + ipvpn_domain_id: str | UndefinedType = Undefined, + enable_d_path: bool | UndefinedType = Undefined, + maximum_routes: int | UndefinedType = Undefined, + local_as: str | None | UndefinedType = Undefined, + address_families: AddressFamilies | UndefinedType = Undefined, + remote_peers: RemotePeers | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + IpvpnGateway. + + + Subclass of AvdModel. + + Args: + enabled: enabled + evpn_domain_id: Domain ID to assign to EVPN address family for use with D-path. Format :. + ipvpn_domain_id: Domain ID to assign to IPVPN address families for use with D-path. Format :. + enable_d_path: Enable D-path for use with BGP bestpath selection algorithm. + maximum_routes: Maximum routes to accept from IPVPN remote peers. + local_as: + Local BGP AS applied to peering with IPVPN remote peers. + BGP AS <1-4294967295> or AS number in asdot + notation "<1-65535>.<0-65535>". + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number. + address_families: + IPVPN address families to enable for remote peers. + + Subclass of AvdList with `str` items. + remote_peers: Subclass of AvdIndexedList with `RemotePeersItem` items. Primary key is `hostname` (`str`). + _custom_data: _custom_data + + """ + + class MlagInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MlagInterfaces._item_type = str + + class OverlayAddressFamilies(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + OverlayAddressFamilies._item_type = str + + class MplsRouteReflectors(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + MplsRouteReflectors._item_type = str + + class Ptp(AvdModel): + """Subclass of AvdModel.""" + + class Dscp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"general_messages": {"type": int}, "event_messages": {"type": int}, "_custom_data": {"type": dict}} + general_messages: int | None + event_messages: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + general_messages: int | None | UndefinedType = Undefined, + event_messages: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Dscp. + + + Subclass of AvdModel. + + Args: + general_messages: general_messages + event_messages: event_messages + _custom_data: _custom_data + + """ + + class Monitor(AvdModel): + """Subclass of AvdModel.""" + + class Threshold(AvdModel): + """Subclass of AvdModel.""" + + class Drop(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "offset_from_master": {"type": int}, + "mean_path_delay": {"type": int}, + "_custom_data": {"type": dict}, + } + offset_from_master: int | None + mean_path_delay: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + offset_from_master: int | None | UndefinedType = Undefined, + mean_path_delay: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Drop. + + + Subclass of AvdModel. + + Args: + offset_from_master: offset_from_master + mean_path_delay: mean_path_delay + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "offset_from_master": {"type": int, "default": 250}, + "mean_path_delay": {"type": int, "default": 1500}, + "drop": {"type": Drop}, + "_custom_data": {"type": dict}, + } + offset_from_master: int + """Default value: `250`""" + mean_path_delay: int + """Default value: `1500`""" + drop: Drop + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + offset_from_master: int | UndefinedType = Undefined, + mean_path_delay: int | UndefinedType = Undefined, + drop: Drop | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Threshold. + + + Subclass of AvdModel. + + Args: + offset_from_master: offset_from_master + mean_path_delay: mean_path_delay + drop: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class MissingMessage(AvdModel): + """Subclass of AvdModel.""" + + class Intervals(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "announce": {"type": int}, + "follow_up": {"type": int}, + "sync": {"type": int}, + "_custom_data": {"type": dict}, + } + announce: int | None + follow_up: int | None + sync: int | None + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + announce: int | None | UndefinedType = Undefined, + follow_up: int | None | UndefinedType = Undefined, + sync: int | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Intervals. + + + Subclass of AvdModel. + + Args: + announce: announce + follow_up: follow_up + sync: sync + _custom_data: _custom_data + + """ + + class SequenceIds(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "announce": {"type": int, "default": 3}, + "delay_resp": {"type": int, "default": 3}, + "follow_up": {"type": int, "default": 3}, + "sync": {"type": int, "default": 3}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + announce: int + """Default value: `3`""" + delay_resp: int + """Default value: `3`""" + follow_up: int + """Default value: `3`""" + sync: int + """Default value: `3`""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + announce: int | UndefinedType = Undefined, + delay_resp: int | UndefinedType = Undefined, + follow_up: int | UndefinedType = Undefined, + sync: int | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + SequenceIds. + + + Subclass of AvdModel. + + Args: + enabled: enabled + announce: announce + delay_resp: delay_resp + follow_up: follow_up + sync: sync + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "intervals": {"type": Intervals}, + "sequence_ids": {"type": SequenceIds}, + "_custom_data": {"type": dict}, + } + intervals: Intervals + """Subclass of AvdModel.""" + sequence_ids: SequenceIds + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + intervals: Intervals | UndefinedType = Undefined, + sequence_ids: SequenceIds | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + MissingMessage. + + + Subclass of AvdModel. + + Args: + intervals: Subclass of AvdModel. + sequence_ids: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool, "default": True}, + "threshold": {"type": Threshold}, + "missing_message": {"type": MissingMessage}, + "_custom_data": {"type": dict}, + } + enabled: bool + """Default value: `True`""" + threshold: Threshold + """Subclass of AvdModel.""" + missing_message: MissingMessage + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | UndefinedType = Undefined, + threshold: Threshold | UndefinedType = Undefined, + missing_message: MissingMessage | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Monitor. + + + Subclass of AvdModel. + + Args: + enabled: enabled + threshold: Subclass of AvdModel. + missing_message: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "profile": {"type": str}, + "mlag": {"type": bool, "default": False}, + "domain": {"type": int, "default": 127}, + "priority1": {"type": int}, + "priority2": {"type": int}, + "auto_clock_identity": {"type": bool}, + "clock_identity_prefix": {"type": str, "default": "00:1C:73"}, + "clock_identity": {"type": str}, + "source_ip": {"type": str}, + "mode": {"type": str, "default": "boundary"}, + "mode_one_step": {"type": bool, "default": False}, + "ttl": {"type": int}, + "forward_unicast": {"type": bool, "default": False}, + "dscp": {"type": Dscp}, + "monitor": {"type": Monitor}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + profile: str | None + """ + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + """ + mlag: bool + """ + Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be + configured on the MLAG peer-link port-channel. + + Default value: `False` + """ + domain: int + """Default value: `127`""" + priority1: int | None + """default -> automatically set based on node_type.""" + priority2: int | None + """default -> (node_id modulus 256).""" + auto_clock_identity: bool | None + """ + If you prefer to have PTP clock identity be the system MAC-address of the switch, which is the + default EOS behaviour, simply disable the automatic PTP clock identity. + default -> + (clock_identity_prefix = 00:1C:73 (default)) + (PTP priority 1 as HEX) + ":00:" + (PTP priority 2 as + HEX). + """ + clock_identity_prefix: str + """ + PTP clock idetentiy 3-byte prefix. i.e. "01:02:03". + By default the 3-byte prefix is "00:1C:73". + This + can be overridden if auto_clock_identity is set to true (which is the default). + + Default value: `"00:1C:73"` + """ + clock_identity: str | None + """Set PTP clock identity manually. 6-byte value i.e. "01:02:03:04:05:06".""" + source_ip: str | None + """ + By default in EOS, PTP packets are sourced with an IP address from the routed port or from the + relevant SVI, which is the recommended behaviour. + This can be set manually if required, for example, + to a value of "10.1.2.3". + """ + mode: Literal["boundary"] + """Default value: `"boundary"`""" + mode_one_step: bool + """Default value: `False`""" + ttl: int | None + forward_unicast: bool + """ + Enable PTP unicast forwarding. + + Default value: `False` + """ + dscp: Dscp + """Subclass of AvdModel.""" + monitor: Monitor + """Subclass of AvdModel.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + profile: str | None | UndefinedType = Undefined, + mlag: bool | UndefinedType = Undefined, + domain: int | UndefinedType = Undefined, + priority1: int | None | UndefinedType = Undefined, + priority2: int | None | UndefinedType = Undefined, + auto_clock_identity: bool | None | UndefinedType = Undefined, + clock_identity_prefix: str | UndefinedType = Undefined, + clock_identity: str | None | UndefinedType = Undefined, + source_ip: str | None | UndefinedType = Undefined, + mode: Literal["boundary"] | UndefinedType = Undefined, + mode_one_step: bool | UndefinedType = Undefined, + ttl: int | None | UndefinedType = Undefined, + forward_unicast: bool | UndefinedType = Undefined, + dscp: Dscp | UndefinedType = Undefined, + monitor: Monitor | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Ptp. + + + Subclass of AvdModel. + + Args: + enabled: enabled + profile: + Default available profiles are: + - "aes67" + - "aes67-r16-2016" + - "smpte2059-2" + mlag: + Configure PTP on the MLAG peer-link port-channel when PTP is enabled. By default PTP will not be + configured on the MLAG peer-link port-channel. + domain: domain + priority1: default -> automatically set based on node_type. + priority2: default -> (node_id modulus 256). + auto_clock_identity: + If you prefer to have PTP clock identity be the system MAC-address of the switch, which is the + default EOS behaviour, simply disable the automatic PTP clock identity. + default -> + (clock_identity_prefix = 00:1C:73 (default)) + (PTP priority 1 as HEX) + ":00:" + (PTP priority 2 as + HEX). + clock_identity_prefix: + PTP clock idetentiy 3-byte prefix. i.e. "01:02:03". + By default the 3-byte prefix is "00:1C:73". + This + can be overridden if auto_clock_identity is set to true (which is the default). + clock_identity: Set PTP clock identity manually. 6-byte value i.e. "01:02:03:04:05:06". + source_ip: + By default in EOS, PTP packets are sourced with an IP address from the routed port or from the + relevant SVI, which is the recommended behaviour. + This can be set manually if required, for example, + to a value of "10.1.2.3". + mode: mode + mode_one_step: mode_one_step + ttl: ttl + forward_unicast: Enable PTP unicast forwarding. + dscp: Subclass of AvdModel. + monitor: Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class WanHa(AvdModel): + """Subclass of AvdModel.""" + + class HaInterfaces(AvdList[str]): + """Subclass of AvdList with `str` items.""" + + HaInterfaces._item_type = str + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = { + "enabled": {"type": bool}, + "ipsec": {"type": bool, "default": True}, + "mtu": {"type": int, "default": 9194}, + "ha_interfaces": {"type": HaInterfaces}, + "ha_ipv4_pool": {"type": str}, + "max_ha_interfaces": {"type": int}, + "port_channel_id": {"type": int}, + "use_port_channel_for_direct_ha": {"type": bool, "default": True}, + "flow_tracking": {"type": FlowTracking}, + "_custom_data": {"type": dict}, + } + enabled: bool | None + """Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group.""" + ipsec: bool + """ + Enable / Disable IPsec over HA path-group when HA is enabled. + + Default value: `True` + """ + mtu: int + """ + Set MTU on WAN HA interfaces. + + Default value: `9194` + """ + ha_interfaces: HaInterfaces + """ + Local WAN HA interfaces + Overwrite the default behavior which is to pick all the `uplink_interfaces`. + Can be used to filter uplink interfaces when there are multiple uplinks. + Limitations: + Either all + interfaces must be uplinks or all interfaces must not be uplinks. + Only one interface is supported + for non uplinks. + + Subclass of AvdList with `str` items. + """ + ha_ipv4_pool: str | None + """ + IP address pool used for WAN HA connectivity. + IP is derived from the node ID. + Not used for uplink + interfaces. + """ + max_ha_interfaces: int | None + """ + Number of parallel links towards HA switches. + Can be used to reserve IP addresses for future + parallel HA links. + """ + port_channel_id: int | None + """Port-channel ID to use for direct HA.""" + use_port_channel_for_direct_ha: bool + """ + Enable or disable using a port-channel interface for direct HA when there is only one interface. + This feature was introduced in EOS 4.33.0F. + + Default value: `True` + """ + flow_tracking: FlowTracking + """ + Configures flow-tracking on the HA interfaces. Overrides `fabric_flow_tracking.wan_ha_links` + setting. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + ipsec: bool | UndefinedType = Undefined, + mtu: int | UndefinedType = Undefined, + ha_interfaces: HaInterfaces | UndefinedType = Undefined, + ha_ipv4_pool: str | None | UndefinedType = Undefined, + max_ha_interfaces: int | None | UndefinedType = Undefined, + port_channel_id: int | None | UndefinedType = Undefined, + use_port_channel_for_direct_ha: bool | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + WanHa. + + + Subclass of AvdModel. + + Args: + enabled: Enable / Disable auto CV-Pathfinder HA, when two nodes are defined in the same node_group. + ipsec: Enable / Disable IPsec over HA path-group when HA is enabled. + mtu: Set MTU on WAN HA interfaces. + ha_interfaces: + Local WAN HA interfaces + Overwrite the default behavior which is to pick all the `uplink_interfaces`. + Can be used to filter uplink interfaces when there are multiple uplinks. + Limitations: + Either all + interfaces must be uplinks or all interfaces must not be uplinks. + Only one interface is supported + for non uplinks. + + Subclass of AvdList with `str` items. + ha_ipv4_pool: + IP address pool used for WAN HA connectivity. + IP is derived from the node ID. + Not used for uplink + interfaces. + max_ha_interfaces: + Number of parallel links towards HA switches. + Can be used to reserve IP addresses for future + parallel HA links. + port_channel_id: Port-channel ID to use for direct HA. + use_port_channel_for_direct_ha: + Enable or disable using a port-channel interface for direct HA when there is only one interface. + This feature was introduced in EOS 4.33.0F. + flow_tracking: + Configures flow-tracking on the HA interfaces. Overrides `fabric_flow_tracking.wan_ha_links` + setting. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L3InterfacesItem(AvdModel): + """Subclass of AvdModel.""" + + class Bgp(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "peer_as": {"type": str}, + "ipv4_prefix_list_in": {"type": str}, + "ipv4_prefix_list_out": {"type": str}, + "_custom_data": {"type": dict}, + } + peer_as: str + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + """ + ipv4_prefix_list_in: str | None + """ + Prefix List Name. Accept routes for only these prefixes from the peer. + Required for wan interfaces. + """ + ipv4_prefix_list_out: str | None + """ + Prefix List Name. Advertise routes for only these prefixes. + If not specified, nothing would be + advertised. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + peer_as: str | UndefinedType = Undefined, + ipv4_prefix_list_in: str | None | UndefinedType = Undefined, + ipv4_prefix_list_out: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + Bgp. + + + Subclass of AvdModel. + + Args: + peer_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + ipv4_prefix_list_in: + Prefix List Name. Accept routes for only these prefixes from the peer. + Required for wan interfaces. + ipv4_prefix_list_out: + Prefix List Name. Advertise routes for only these prefixes. + If not specified, nothing would be + advertised. + _custom_data: _custom_data + + """ + + class StaticRoutesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"prefix": {"type": str}, "_custom_data": {"type": dict}} + prefix: str + """IPv4_network/Mask.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, prefix: str | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + StaticRoutesItem. + + + Subclass of AvdModel. + + Args: + prefix: IPv4_network/Mask. + _custom_data: _custom_data + + """ + + class StaticRoutes(AvdList[StaticRoutesItem]): + """Subclass of AvdList with `StaticRoutesItem` items.""" + + StaticRoutes._item_type = StaticRoutesItem + + class CvPathfinderInternetExit(AvdModel): + """Subclass of AvdModel.""" + + class PoliciesItem(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"name": {"type": str}, "tunnel_interface_numbers": {"type": str}, "_custom_data": {"type": dict}} + name: str + """Internet-exit policy name.""" + tunnel_interface_numbers: str | None + """ + Number range to use for Tunnel interfaces to an internet-exit service provider using this local + interface. + Examples: '1-3' or '100,200,300' + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + tunnel_interface_numbers: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + PoliciesItem. + + + Subclass of AvdModel. + + Args: + name: Internet-exit policy name. + tunnel_interface_numbers: + Number range to use for Tunnel interfaces to an internet-exit service provider using this local + interface. + Examples: '1-3' or '100,200,300' + _custom_data: _custom_data + + """ + + class Policies(AvdIndexedList[str, PoliciesItem]): + """Subclass of AvdIndexedList with `PoliciesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Policies._item_type = PoliciesItem + + _fields: ClassVar[dict] = {"policies": {"type": Policies}, "_custom_data": {"type": dict}} + policies: Policies + """ + List of Internet-exit policies using this interface as exit. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, *, policies: Policies | UndefinedType = Undefined, _custom_data: dict[str, Any] | UndefinedType = Undefined + ) -> None: + """ + CvPathfinderInternetExit. + + + Subclass of AvdModel. + + Args: + policies: + List of Internet-exit policies using this interface as exit. + + Subclass of AvdIndexedList with + `PoliciesItem` items. Primary key is `name` (`str`). + _custom_data: _custom_data + + """ + + class FlowTracking(AvdModel): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = {"enabled": {"type": bool}, "name": {"type": str}, "_custom_data": {"type": dict}} + enabled: bool | None + name: str | None + """Flow tracker name as defined in flow_tracking_settings.""" + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + enabled: bool | None | UndefinedType = Undefined, + name: str | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + FlowTracking. + + + Subclass of AvdModel. + + Args: + enabled: enabled + name: Flow tracker name as defined in flow_tracking_settings. + _custom_data: _custom_data + + """ + + class StructuredConfig(EosCliConfigGen.EthernetInterfacesItem): + """Subclass of AvdModel.""" + + _fields: ClassVar[dict] = { + "profile": {"type": str}, + "name": {"type": str}, + "description": {"type": str}, + "ip_address": {"type": str}, + "dhcp_ip": {"type": str}, + "public_ip": {"type": str}, + "encapsulation_dot1q_vlan": {"type": int}, + "dhcp_accept_default_route": {"type": bool, "default": True}, + "enabled": {"type": bool, "default": True}, + "speed": {"type": str}, + "peer": {"type": str}, + "peer_interface": {"type": str}, + "peer_ip": {"type": str}, + "bgp": {"type": Bgp}, + "ipv4_acl_in": {"type": str}, + "ipv4_acl_out": {"type": str}, + "static_routes": {"type": StaticRoutes}, + "qos_profile": {"type": str}, + "wan_carrier": {"type": str}, + "wan_circuit_id": {"type": str}, + "connected_to_pathfinder": {"type": bool, "default": True}, + "cv_pathfinder_internet_exit": {"type": CvPathfinderInternetExit}, + "raw_eos_cli": {"type": str}, + "flow_tracking": {"type": FlowTracking}, + "structured_config": {"type": StructuredConfig}, + "_custom_data": {"type": dict}, + } + profile: str | None + """L3 interface profile name. Profile defined under `l3_interface_profiles`.""" + name: str + """ + Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. + For a + subinterface, the parent physical interface is automatically created. + """ + description: str | None + """ + Interface description. + If not set a default description will be configured with '[[ + ]]'. + """ + ip_address: str | None + """Node IPv4 address/Mask or 'dhcp'.""" + dhcp_ip: str | None + """ + When the `ip_address` is `dhcp`, this optional field allows to indicate the expected + IPv4 address + (without mask) to be allocated on the interface if known. + This is not rendered in the configuration + but can be used for substitution of 'interface_ip' in the Access-list + set under `ipv4_acl_in` and + `ipv4_acl_out`. + """ + public_ip: str | None + """ + Node IPv4 address (no mask). + + This is used to get the public IP (if known) when the device is behind + NAT. + This is only used for `wan_rr` routers (AutoVPN RRs and Pathfinders) to determine the Public IP + with the following preference: + `wan_route_servers.path_groups.interfaces.ip_address` + -> + `l3_interfaces.public_ip` + -> `l3_interfaces.ip_address` + + The determined Public IP is used + by WAN routers when peering with this interface. + """ + encapsulation_dot1q_vlan: int | None + """ + For subinterfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + """ + dhcp_accept_default_route: bool + """ + Accept a default route from DHCP if `ip_address` is set to `dhcp`. + + Default value: `True` + """ + enabled: bool + """ + Enable or Shutdown the interface. + + Default value: `True` + """ + speed: str | None + """ + Speed should be set in the format `` or `forced ` or `auto + `. + """ + peer: str | None + """The peer device name. Used for description and documentation.""" + peer_interface: str | None + """The peer device interface. Used for description and documentation.""" + peer_ip: str | None + """ + The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true + and `ip` is an IP address. + """ + bgp: Bgp + """ + Enforce IPv4 BGP peering for the peer + + Subclass of AvdModel. + """ + ipv4_acl_in: str | None + """ + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + Required + for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under + `wan_carriers`. + """ + ipv4_acl_out: str | None + """ + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + """ + static_routes: StaticRoutes + """ + Configure IPv4 static routes pointing to `peer_ip`. + + Subclass of AvdList with `StaticRoutesItem` + items. + """ + qos_profile: str | None + """QOS service profile.""" + wan_carrier: str | None + """ + The WAN carrier this interface is connected to. + This is used to infer the path-groups in which this + interface should be configured. + Unless the carrier is marked as 'trusted' under `wan_carriers`, + `ipv4_acl_in` is also required on all WAN interfaces. + """ + wan_circuit_id: str | None + """ + The WAN circuit ID for this interface. + This is not rendered in the configuration but used for WAN + designs. + """ + connected_to_pathfinder: bool + """ + For a WAN interface (`wan_carrier` is set), allow to disable the static tunnel towards Pathfinders. + + Default value: `True` + """ + cv_pathfinder_internet_exit: CvPathfinderInternetExit + """ + PREVIEW: This key is in preview mode + + Subclass of AvdModel. + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the interface in the final EOS configuration.""" + flow_tracking: FlowTracking + """ + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + """ + structured_config: StructuredConfig + """ + Custom structured config for the Ethernet interface. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + profile: str | None | UndefinedType = Undefined, + name: str | UndefinedType = Undefined, + description: str | None | UndefinedType = Undefined, + ip_address: str | None | UndefinedType = Undefined, + dhcp_ip: str | None | UndefinedType = Undefined, + public_ip: str | None | UndefinedType = Undefined, + encapsulation_dot1q_vlan: int | None | UndefinedType = Undefined, + dhcp_accept_default_route: bool | UndefinedType = Undefined, + enabled: bool | UndefinedType = Undefined, + speed: str | None | UndefinedType = Undefined, + peer: str | None | UndefinedType = Undefined, + peer_interface: str | None | UndefinedType = Undefined, + peer_ip: str | None | UndefinedType = Undefined, + bgp: Bgp | UndefinedType = Undefined, + ipv4_acl_in: str | None | UndefinedType = Undefined, + ipv4_acl_out: str | None | UndefinedType = Undefined, + static_routes: StaticRoutes | UndefinedType = Undefined, + qos_profile: str | None | UndefinedType = Undefined, + wan_carrier: str | None | UndefinedType = Undefined, + wan_circuit_id: str | None | UndefinedType = Undefined, + connected_to_pathfinder: bool | UndefinedType = Undefined, + cv_pathfinder_internet_exit: CvPathfinderInternetExit | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + flow_tracking: FlowTracking | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + L3InterfacesItem. + + + Subclass of AvdModel. + + Args: + profile: L3 interface profile name. Profile defined under `l3_interface_profiles`. + name: + Ethernet interface name like 'Ethernet2' or subinterface name like 'Ethernet2.42'. + For a + subinterface, the parent physical interface is automatically created. + description: + Interface description. + If not set a default description will be configured with '[[ + ]]'. + ip_address: Node IPv4 address/Mask or 'dhcp'. + dhcp_ip: + When the `ip_address` is `dhcp`, this optional field allows to indicate the expected + IPv4 address + (without mask) to be allocated on the interface if known. + This is not rendered in the configuration + but can be used for substitution of 'interface_ip' in the Access-list + set under `ipv4_acl_in` and + `ipv4_acl_out`. + public_ip: + Node IPv4 address (no mask). + + This is used to get the public IP (if known) when the device is behind + NAT. + This is only used for `wan_rr` routers (AutoVPN RRs and Pathfinders) to determine the Public IP + with the following preference: + `wan_route_servers.path_groups.interfaces.ip_address` + -> + `l3_interfaces.public_ip` + -> `l3_interfaces.ip_address` + + The determined Public IP is used + by WAN routers when peering with this interface. + encapsulation_dot1q_vlan: + For subinterfaces the dot1q vlan is derived from the interface name by default, but can also be + specified. + dhcp_accept_default_route: Accept a default route from DHCP if `ip_address` is set to `dhcp`. + enabled: Enable or Shutdown the interface. + speed: + Speed should be set in the format `` or `forced ` or `auto + `. + peer: The peer device name. Used for description and documentation. + peer_interface: The peer device interface. Used for description and documentation. + peer_ip: + The peer device IPv4 address (no mask). Used as default route gateway if `set_default_route` is true + and `ip` is an IP address. + bgp: + Enforce IPv4 BGP peering for the peer + + Subclass of AvdModel. + ipv4_acl_in: + Name of the IPv4 access-list to be assigned in the ingress direction. + The access-list must be + defined under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + Required + for all WAN interfaces (`wan_carrier` is set) unless the carrier is marked as 'trusted' under + `wan_carriers`. + ipv4_acl_out: + Name of the IPv4 Access-list to be assigned in the egress direction. + The access-list must be defined + under `ipv4_acls` and supports field substitution for "interface_ip" and "peer_ip". + static_routes: + Configure IPv4 static routes pointing to `peer_ip`. + + Subclass of AvdList with `StaticRoutesItem` + items. + qos_profile: QOS service profile. + wan_carrier: + The WAN carrier this interface is connected to. + This is used to infer the path-groups in which this + interface should be configured. + Unless the carrier is marked as 'trusted' under `wan_carriers`, + `ipv4_acl_in` is also required on all WAN interfaces. + wan_circuit_id: + The WAN circuit ID for this interface. + This is not rendered in the configuration but used for WAN + designs. + connected_to_pathfinder: For a WAN interface (`wan_carrier` is set), allow to disable the static tunnel towards Pathfinders. + cv_pathfinder_internet_exit: + PREVIEW: This key is in preview mode + + Subclass of AvdModel. + raw_eos_cli: EOS CLI rendered directly on the interface in the final EOS configuration. + flow_tracking: + Configures flow-tracking on the interface. Overrides `fabric_flow_tracking.l3_interfaces` setting. + Subclass of AvdModel. + structured_config: + Custom structured config for the Ethernet interface. + + Subclass of AvdModel. + _custom_data: _custom_data + + """ + + class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): + """Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + L3Interfaces._item_type = L3InterfacesItem + + _fields: ClassVar[dict] = { + "name": {"type": str}, + "downlink_pools": {"type": DownlinkPools}, + "id": {"type": int}, + "platform": {"type": str}, + "mac_address": {"type": str}, + "system_mac_address": {"type": str}, + "serial_number": {"type": str}, + "rack": {"type": str}, + "mgmt_ip": {"type": str}, + "mgmt_gateway": {"type": str}, + "ipv6_mgmt_ip": {"type": str}, + "ipv6_mgmt_gateway": {"type": str}, + "mgmt_interface": {"type": str}, + "link_tracking": {"type": LinkTracking}, + "lacp_port_id_range": {"type": LacpPortIdRange}, + "always_configure_ip_routing": {"type": bool, "default": False}, + "raw_eos_cli": {"type": str}, + "structured_config": {"type": StructuredConfig}, + "uplink_type": {"type": str}, + "uplink_ipv4_pool": {"type": str}, + "uplink_interfaces": {"type": UplinkInterfaces}, + "uplink_switch_interfaces": {"type": UplinkSwitchInterfaces}, + "uplink_switches": {"type": UplinkSwitches}, + "uplink_interface_speed": {"type": str}, + "uplink_switch_interface_speed": {"type": str}, + "uplink_mtu": {"type": int}, + "max_uplink_switches": {"type": int}, + "max_parallel_uplinks": {"type": int, "default": 1}, + "uplink_bfd": {"type": bool, "default": False}, + "uplink_native_vlan": {"type": int}, + "uplink_ptp": {"type": UplinkPtp}, + "uplink_macsec": {"type": UplinkMacsec}, + "uplink_port_channel_id": {"type": int}, + "uplink_switch_port_channel_id": {"type": int}, + "uplink_structured_config": {"type": dict}, + "mlag_port_channel_structured_config": {"type": MlagPortChannelStructuredConfig}, + "mlag_peer_vlan_structured_config": {"type": MlagPeerVlanStructuredConfig}, + "mlag_peer_l3_vlan_structured_config": {"type": MlagPeerL3VlanStructuredConfig}, + "short_esi": {"type": str}, + "isis_system_id_prefix": {"type": str}, + "isis_maximum_paths": {"type": int}, + "is_type": {"type": str}, + "node_sid_base": {"type": int, "default": 0}, + "loopback_ipv4_pool": {"type": str}, + "loopback_ipv4_address": {"type": str}, + "vtep_loopback_ipv4_pool": {"type": str}, + "vtep_loopback_ipv4_address": {"type": str}, + "loopback_ipv4_offset": {"type": int, "default": 0}, + "loopback_ipv6_pool": {"type": str}, + "loopback_ipv6_offset": {"type": int, "default": 0}, + "vtep": {"type": bool}, + "vtep_loopback": {"type": str}, + "bgp_as": {"type": str}, + "bgp_defaults": {"type": BgpDefaults}, + "evpn_role": {"type": str}, + "evpn_route_servers": {"type": EvpnRouteServers}, + "evpn_services_l2_only": {"type": bool, "default": False}, + "filter": {"type": Filter}, + "igmp_snooping_enabled": {"type": bool}, + "evpn_gateway": {"type": EvpnGateway}, + "ipvpn_gateway": {"type": IpvpnGateway}, + "mlag": {"type": bool, "default": True}, + "mlag_dual_primary_detection": {"type": bool, "default": False}, + "mlag_ibgp_origin_incomplete": {"type": bool, "default": True}, + "mlag_interfaces": {"type": MlagInterfaces}, + "mlag_interfaces_speed": {"type": str}, + "mlag_peer_l3_vlan": {"type": int, "default": 4093}, + "mlag_peer_l3_ipv4_pool": {"type": str}, + "mlag_peer_vlan": {"type": int, "default": 4094}, + "mlag_peer_link_allowed_vlans": {"type": str}, + "mlag_peer_address_family": {"type": str, "default": "ipv4"}, + "mlag_peer_ipv4_pool": {"type": str}, + "mlag_peer_ipv6_pool": {"type": str}, + "mlag_port_channel_id": {"type": int}, + "mlag_domain_id": {"type": str}, + "spanning_tree_mode": {"type": str}, + "spanning_tree_priority": {"type": int, "default": 32768}, + "spanning_tree_root_super": {"type": bool, "default": False}, + "virtual_router_mac_address": {"type": str}, + "inband_mgmt_interface": {"type": str}, + "inband_mgmt_vlan": {"type": int, "default": 4092}, + "inband_mgmt_subnet": {"type": str}, + "inband_mgmt_ip": {"type": str}, + "inband_mgmt_gateway": {"type": str}, + "inband_mgmt_ipv6_address": {"type": str}, + "inband_mgmt_ipv6_subnet": {"type": str}, + "inband_mgmt_ipv6_gateway": {"type": str}, + "inband_mgmt_description": {"type": str, "default": "Inband Management"}, + "inband_mgmt_vlan_name": {"type": str, "default": "INBAND_MGMT"}, + "inband_mgmt_vrf": {"type": str, "default": "default"}, + "inband_mgmt_mtu": {"type": int, "default": 1500}, + "inband_ztp": {"type": bool, "default": False}, + "inband_ztp_lacp_fallback_delay": {"type": int, "default": 30}, + "mpls_overlay_role": {"type": str}, + "overlay_address_families": {"type": OverlayAddressFamilies}, + "mpls_route_reflectors": {"type": MplsRouteReflectors}, + "bgp_cluster_id": {"type": str}, + "ptp": {"type": Ptp}, + "wan_role": {"type": str}, + "cv_pathfinder_transit_mode": {"type": str}, + "cv_pathfinder_region": {"type": str}, + "cv_pathfinder_site": {"type": str}, + "wan_ha": {"type": WanHa}, + "dps_mss_ipv4": {"type": str, "default": "auto"}, + "l3_interfaces": {"type": L3Interfaces}, + "data_plane_cpu_allocation_max": {"type": int}, + "flow_tracker_type": {"type": str}, + "_custom_data": {"type": dict}, + } + name: str + """The Node Name is used as "hostname".""" + downlink_pools: DownlinkPools + """ + IPv4 pools used for links to downlink switches. Set this on the parent switch. Cannot be combined + with `uplink_ipv4_pool` set on the downlink switch. + + Subclass of AvdList with `DownlinkPoolsItem` + items. + """ + id: int | None + """Unique identifier used for IP addressing and other algorithms.""" + platform: str | None + """Arista platform family.""" + mac_address: str | None + """Leverage to document management interface mac address.""" + system_mac_address: str | None + """ + System MAC Address in this following format: "xx:xx:xx:xx:xx:xx". + Set to the same MAC address as + available in "show version" on the device. + "system_mac_address" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + """ + serial_number: str | None + """ + Set to the Serial Number of the device. + Only used for documentation purpose in the fabric + documentation and part of the structured_config. + "serial_number" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + """ + rack: str | None + """Rack that the switch is located in (only used in snmp_settings location).""" + mgmt_ip: str | None + """Node management interface IPv4 address.""" + mgmt_gateway: str | None + """ + This key sets the management gateway for the device. It takes precedence over the global + `mgmt_gateway`. + """ + ipv6_mgmt_ip: str | None + """Node management interface IPv6 address.""" + ipv6_mgmt_gateway: str | None + """ + This key sets the ipv6 management gateway for the device. It takes precedence over the global + `ipv6_mgmt_gateway`. + """ + mgmt_interface: str | None + """ + Management Interface Name. + Default -> platform_management_interface -> mgmt_interface -> + "Management1". + """ + link_tracking: LinkTracking + """ + This configures the Link Tracking Group on a switch as well as adds the p2p-uplinks of the switch as + the upstream interfaces. + Useful in EVPN multhoming designs. + + + Subclass of AvdModel. + """ + lacp_port_id_range: LacpPortIdRange + """ + This will generate the "lacp port-id range", "begin" and "end" values based on node "id" and the + number of nodes in the "node_group". + Unique LACP port-id ranges are recommended for EVPN Multihoming + designs. + + + Subclass of AvdModel. + """ + always_configure_ip_routing: bool + """ + Force configuration of "ip routing" even on L2 devices. + Use this to retain behavior of AVD versions + below 4.0.0. + + Default value: `False` + """ + raw_eos_cli: str | None + """EOS CLI rendered directly on the root level of the final EOS configuration.""" + structured_config: StructuredConfig + """ + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + """ + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None + """ + Override the default `uplink_type` set at the `node_type_key` level. + `uplink_type` must be "p2p" if + `vtep` or `underlay_router` is true for the `node_type_key` definition. + """ + uplink_ipv4_pool: str | None + """IPv4 subnet to use to connect to uplink switches.""" + uplink_interfaces: UplinkInterfaces + """ + Local uplink interfaces. + Each list item supports range syntax that can be expanded into a list of + interfaces. + If uplink_interfaces is not defined, platform-specific defaults (defined under + default_interfaces) will be used instead. + Please note that default_interfaces are not defined by + default, you should define these yourself. + + + Subclass of AvdList with `str` items. + """ + uplink_switch_interfaces: UplinkSwitchInterfaces + """ + Interfaces located on uplink switches. + + Subclass of AvdList with `str` items. + """ + uplink_switches: UplinkSwitches + """Subclass of AvdList with `str` items.""" + uplink_interface_speed: str | None + """ + Set point-to-Point interface speed and will apply to uplink interfaces on both ends. + (Uplink switch + interface speed can be overridden with `uplink_switch_interface_speed`). + Speed should be set in the + format `` or `forced ` or `auto `. + """ + uplink_switch_interface_speed: str | None + """ + 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: int | None + """Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting.""" + max_uplink_switches: int | None + """ + 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: 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 + """ + Enable bfd on uplink interfaces. + + Default value: `False` + """ + uplink_native_vlan: int | None + """ + 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: UplinkPtp + """ + Enable PTP on all infrastructure links. + + Subclass of AvdModel. + """ + uplink_macsec: UplinkMacsec + """ + Enable MacSec on all uplinks. + + Subclass of AvdModel. + """ + uplink_port_channel_id: int | None + """ + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink Port-channel + ID will be set to the number of the lowest member interface defined under `uplink_interfaces`. + For + example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ Eth11/1, Eth22/1 ] -> ID 111 + For + MLAG port-channels ID will be based on the lowest member interface on the first MLAG switch. + This + option overrides the default behavior and statically sets the local Port-channel ID. + Note! Make sure + the ID is unique and does not overlap with autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between 1 and 2000 and both MLAG switches must have the same + value. + """ + uplink_switch_port_channel_id: int | None + """ + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink switch Port- + channel ID will be set to the number of the first interface defined under + `uplink_switch_interfaces`. + For example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ + Eth11/1, Eth22/1 ] -> ID 111 + For MLAG port-channels ID will be based on the lowest member interface + on the first MLAG switch. + This option overrides the default behavior and statically sets the Port- + channel ID on the uplink switch. + Note! Make sure the ID is unique and does not overlap with + autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between + 1 and 2000 and both MLAG switches must have the same value. + """ + uplink_structured_config: dict + """ + Custom structured config applied to "uplink_interfaces", and "uplink_switch_interfaces". + When + uplink_type == "p2p", custom structured config added under ethernet_interfaces.[name=] + for eos_cli_config_gen overrides the settings on the ethernet interface level. + When uplink_type == + "port-channel", custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen overrides the settings on the port-channel interface level. + "uplink_structured_config" is applied after "structured_config", so it can override + "structured_config" defined on node-level. + Note! The content of this dictionary is _not_ validated + by the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + """ + mlag_port_channel_structured_config: MlagPortChannelStructuredConfig + """ + Custom structured config applied to MLAG peer link port-channel id. + Added under + port_channel_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the + port-channel interface level. + "mlag_port_channel_structured_config" is applied after + "structured_config", so it can override "structured_config" defined on node-level. + + + Subclass of + AvdModel. + """ + mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig + """ + Custom structured config applied to MLAG Peer Link (control link) SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_vlan_structured_config" is applied after "structured_config", so it can + override "structured_config" defined on node-level. + + + Subclass of AvdModel. + """ + mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig + """ + Custom structured config applied to MLAG underlay L3 peering SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_l3_vlan_structured_config" is applied after "structured_config", so it + can override "structured_config" defined on node-level. + + + Subclass of AvdModel. + """ + short_esi: str | None + """ + short_esi only valid for l2leaf devices using port-channel uplink. + Setting short_esi to "auto" + generates the short_esi automatically using a hash of configuration elements. + < 0000:0000:0000 | + auto >. + """ + isis_system_id_prefix: str | None + """(4.4 hexadecimal).""" + isis_maximum_paths: int | None + """Number of path to configure in ECMP for ISIS.""" + is_type: Literal["level-1-2", "level-1", "level-2"] | None + """Overrides `isis_default_is_type`.""" + node_sid_base: int + """ + Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID. + + Default value: `0` + """ + loopback_ipv4_pool: str | None + """IPv4 subnet for Loopback0 allocation.""" + loopback_ipv4_address: str | None + """ + IPv4 address without mask for Loopback0. + When set, it takes precedence over `loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not catch duplicates. + """ + vtep_loopback_ipv4_pool: str | None + """IPv4 subnet for VTEP-Loopback allocation.""" + vtep_loopback_ipv4_address: str | None + """ + IPv4 address without mask for VTEP-Loopback. + When set, it takes precedence over + `vtep_loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not + catch duplicates. + """ + loopback_ipv4_offset: int + """ + Offset all assigned loopback IP addresses. + Required when the < loopback_ipv4_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid over-lapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv4_offset: < total # spine switches > or vice versa. + + Default value: `0` + """ + loopback_ipv6_pool: str | None + """IPv6 subnet for Loopback0 allocation.""" + loopback_ipv6_offset: int + """ + Offset all assigned loopback IPv6 addresses. + Required when the < loopback_ipv6_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid overlapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv6_offset: < total # spine switches > or vice versa. + + Default value: `0` + """ + vtep: bool | None + """ + Node is configured as a VTEP when applicable based on 'overlay_routing_protocol'. + Overrides VTEP + setting inherited from node_type_keys. + """ + vtep_loopback: str | None + """Set VXLAN source interface.""" + bgp_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + Required with eBGP. + """ + bgp_defaults: BgpDefaults + """ + List of EOS commands to apply to BGP daemon. + + Subclass of AvdList with `str` items. + """ + evpn_role: Literal["client", "server", "none"] | None + """ + Acting role in EVPN control plane. + Default is set in node_type definition from node_type_keys. + """ + evpn_route_servers: EvpnRouteServers + """ + List of nodes acting as EVPN Route-Servers / Route-Reflectors. + + Subclass of AvdList with `str` + items. + """ + evpn_services_l2_only: bool + """ + Possibility to prevent configuration of Tenant VRFs and SVIs. + Override node definition + "network_services_l3" from node_type_keys. + This allows support for centralized routing. + + Default value: `False` + """ + filter: Filter + """ + Filter L3 and L2 network services based on tenant and tags (and operation filter). + If filter is not + defined it will default to all. + + + Subclass of AvdModel. + """ + igmp_snooping_enabled: bool | None + """Activate or deactivate IGMP snooping on device level.""" + evpn_gateway: EvpnGateway + """ + Node is acting as EVPN Multi-Domain Gateway. + New BGP peer-group is generated between EVPN GWs in + different domains or between GWs and Route Servers. + Name can be changed under + "bgp_peer_groups.evpn_overlay_core" variable. + L3 rechability for different EVPN GWs must be already + in place, it is recommended to use DCI & L3 Edge if Route Servers and GWs are not defined under the + same Ansible inventory. + + + Subclass of AvdModel. + """ + ipvpn_gateway: IpvpnGateway + """ + Node is acting as IP-VPN Gateway for EVPN to MPLS-IP-VPN Interworking. The BGP peer group used for + this is "bgp_peer_groups.ipvpn_gateway_peers". + L3 Reachability is required for this to work, the + preferred method to establish underlay connectivity is to use core_interfaces. + + + Subclass of + AvdModel. + """ + mlag: bool + """ + Enable / Disable auto MLAG, when two nodes are defined in node group. + + Default value: `True` + """ + mlag_dual_primary_detection: bool + """ + Enable / Disable MLAG dual primary detection. + + Default value: `False` + """ + mlag_ibgp_origin_incomplete: bool + """ + Set origin of routes received from MLAG iBGP peer to incomplete. + The purpose is to optimize routing + for leaf loopbacks from spine perspective and + avoid suboptimal routing via peerlink for control + plane traffic. + + Default value: `True` + """ + mlag_interfaces: MlagInterfaces + """ + Each list item supports range syntax that can be expanded into a list of interfaces. + Required when + MLAG leafs are present in the topology. + + + Subclass of AvdList with `str` items. + """ + mlag_interfaces_speed: str | None + """ + Set MLAG interface speed. + Speed should be set in the format `` or `forced + ` or `auto `. + """ + mlag_peer_l3_vlan: int + """ + Underlay L3 peering SVI interface id. + If set to 0 or the same vlan as mlag_peer_vlan, the + mlag_peer_vlan will be used for L3 peering. + + Default value: `4093` + """ + mlag_peer_l3_ipv4_pool: str | None + """ + IP address pool used for MLAG underlay L3 peering. IP is derived from the node id. + Required when + MLAG leafs present in topology and they are using a separate L3 peering VLAN. + """ + mlag_peer_vlan: int + """ + MLAG Peer Link (control link) SVI interface id. + + Default value: `4094` + """ + mlag_peer_link_allowed_vlans: str | None + mlag_peer_address_family: Literal["ipv4", "ipv6"] + """ + IP address family used to establish MLAG Peer Link (control link). + `ipv6` requires EOS version + 4.31.1F or higher. + Note: `ipv6` is not supported in combination with a common MLAG peer link VLAN + (ex. `mlag_peer_l3_vlan` set to 4094). + + Default value: `"ipv4"` + """ + mlag_peer_ipv4_pool: str | None + """ + IPv4 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv4` (default). + """ + mlag_peer_ipv6_pool: str | None + """ + IPv6 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv6`. + """ + mlag_port_channel_id: int | None + """ + If not set, the mlag port-channel id is generated based on the digits of the first interface present + in 'mlag_interfaces'. + Valid port-channel id numbers are < 1-2000 > for EOS < 4.25.0F and < 1 - + 999999 > for EOS >= 4.25.0F. + """ + mlag_domain_id: str | None + """MLAG Domain ID. If not set the node group name (Set with "group" key) will be used.""" + spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None + spanning_tree_priority: int + """ + Spanning-tree priority configured for the selected mode. + For `rapid-pvst` the priority can also be + set per VLAN under network services. + + Default value: `32768` + """ + spanning_tree_root_super: bool + """Default value: `False`""" + virtual_router_mac_address: str | None + """Virtual router mac address for anycast gateway.""" + inband_mgmt_interface: str | None + """ + Pointer to interface used for inband management. + All configuration must be done using other data + models like network services or structured_config. + 'inband_mgmt_interface' is only used to refer to + this interface as source in various management protocol settings (future feature). + + On L2 switches, + this defaults to Vlan if either 'inband_mgmt_subnet' or 'inband_mgmt_ip' is set. + """ + inband_mgmt_vlan: int + """ + VLAN number used for inband management on L2 switches (switches using port-channel trunks as + uplinks). + When using 'inband_mgmt_subnet' the VLAN and SVIs will be created automatically on this + switch as well as all 'uplink_switches'. + When using 'inband_mgmt_ip' the VLAN and SVI will only be + created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be + created using network services data models. + + Default value: `4092` + """ + inband_mgmt_subnet: str | None + """ + Optional IP subnet assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ip virtual-router" and host-route injection based on + ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + + 3 + + GW on l2leafs : + 1 + Assign range larger than total l2leafs + 5 + Setting is ignored if 'inband_mgmt_ip' is set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + """ + inband_mgmt_ip: str | None + """ + IP address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_subnet', hence all behavior of 'inband_mgmt_subnet' is removed. + + If this is set the + VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN and SVI on + the parent switches must be created using network services data models. + + This setting is applicable + to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_gateway: str | None + """ + Default gateway configured in the 'inband_mgmt_vrf' when using 'inband_mgmt_ip'. Otherwise gateway + is derived from 'inband_mgmt_subnet' if set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_address: str | None + """ + IPv6 address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_ipv6_subnet', hence the configuration of 'inband_mgmt_ipv6_subnet' is ignored. + + If this + is set the VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN + and SVI on the parent switches must be created using network services data models. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_subnet: str | None + """ + Optional IPv6 prefix assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ipv6 virtual-router" and host-route injection based + on ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN + extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + 3 + + GW on l2leafs : + 1 + Assign range larger than + total l2leafs + 5 + + Setting is ignored if 'inband_mgmt_ipv6_address' is set. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_ipv6_gateway: str | None + """ + Default gateway configured in the 'inband_mgmt_vrf'. + Used when `inband_mgmt_ipv6_address` is set. + Ignored when 'inband_mgmt_ipv6_subnet' is set (first IP in subnet used as gateway). + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + """ + inband_mgmt_description: str + """ + Description configured on the Inband Management SVI. + + This setting is only applied on the devices + where it is set, it does not automatically affect any parent/child devices configuration, so it must + be set on each applicable node/node-group/node-type as needed. + + Default value: `"Inband Management"` + """ + inband_mgmt_vlan_name: str + """ + Name configured on the Inband Management VLAN. + This setting is only applied on the devices where it + is set, it does not automatically affect any parent/child devices configuration, so it must be set + on each applicable node/node-group/node-type as needed. + + Default value: `"INBAND_MGMT"` + """ + inband_mgmt_vrf: str + """ + VRF configured on the Inband Management Interface. + The VRF is created if not already created by + other means. + This setting is only applied on the devices where it is set, it does not automatically + affect any parent/child devices configuration, so it must be set on each applicable node/node- + group/node-type as needed. + + Default value: `"default"` + """ + inband_mgmt_mtu: int + """ + MTU configured on the Inband Management Interface. + This setting is only applied on the devices where + it is set, it does not automatically affect any parent/child devices configuration, so it must be + set on each applicable node/node-group/node-type as needed. + + Default value: `1500` + """ + inband_ztp: bool + """ + Enable to configure upstream device with proper configuration to allow downstream devices to be + Zero-Touch-Provisioned over the uplink interfaces. + For L2 devices this setting also requires that + the `inband_mgmt_vlan` is set for the node. + + PREVIEW: Support for L3 devices is marked as "preview", + meaning the data models or generated configuration can change at any time. + + Default value: `False` + """ + inband_ztp_lacp_fallback_delay: int + """ + Set the LACP fallback timeout of the upstream device's port-channel towards the downstream inband + ZTP node. + This setting also requires that `inband_ztp` is set for the node. + + Default value: `30` + """ + mpls_overlay_role: Literal["client", "server", "none"] | None + """ + Set the default mpls overlay role. + Acting role in overlay control plane. + """ + overlay_address_families: OverlayAddressFamilies + """ + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + """ + mpls_route_reflectors: MplsRouteReflectors + """ + List of inventory hostname acting as MPLS route-reflectors. + + Subclass of AvdList with `str` items. + """ + bgp_cluster_id: str | None + """Set BGP cluster id.""" + ptp: Ptp + """Subclass of AvdModel.""" + wan_role: Literal["client", "server"] | None + """ + Override the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + """ + cv_pathfinder_transit_mode: Literal["region", "zone"] | None + """ + Configure the transit mode for a WAN client for CV Pathfinder designs + only when the `wan_mode` root + key is set to `cv_pathfinder`. + + 'zone' is currently not supported. + """ + cv_pathfinder_region: str | None + """ + The CV Pathfinder region name. + This key is required for WAN routers but optional for pathfinders. + The region name must be defined under 'cv_pathfinder_regions'. + """ + cv_pathfinder_site: str | None + """ + The CV Pathfinder site name. + This key is required for WAN routers but optional for pathfinders. + For + WAN routers and pathfinders with `cv_pathfinder_region`, the site name must be defined for the + relevant region under 'cv_pathfinder_regions'. + For pathfinders without `cv_pathfinder_region` set, + the site must be defined under `cv_pathfinder_global_sites`. + """ + wan_ha: WanHa + """ + PREVIEW: This key is currently not supported + + The key is supported only if `wan_mode` == `cv- + pathfinder`. + AutoVPN support is still to be determined. + + Maximum 2 devices supported by group for + HA. + + Subclass of AvdModel. + """ + dps_mss_ipv4: str + """ + IPv4 MSS value configured under "router path-selection" on WAN Devices. + + Default value: `"auto"` + """ + l3_interfaces: L3Interfaces + """ + L3 Interfaces to configure on the node. + Used to define the node for WAN interfaces when + `wan_carrier` is set. + + Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is + `name` (`str`). + """ + data_plane_cpu_allocation_max: int | None + """ + Set the maximum number of CPU used for the data plane. + This setting is useful on virtual Route + Reflectors and Pathfinders where more CPU cores should be allocated for control plane. + """ + flow_tracker_type: Literal["sampled", "hardware"] | None + """ + Set the flow tracker type. + Override the `default_flow_tracker_type`` set at the `node_type_key` + level. + `default_flow_tracker_type` default value is `sampled`. + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + name: str | UndefinedType = Undefined, + downlink_pools: DownlinkPools | UndefinedType = Undefined, + id: int | None | UndefinedType = Undefined, + platform: str | None | UndefinedType = Undefined, + mac_address: str | None | UndefinedType = Undefined, + system_mac_address: str | None | UndefinedType = Undefined, + serial_number: str | None | UndefinedType = Undefined, + rack: str | None | UndefinedType = Undefined, + mgmt_ip: str | None | UndefinedType = Undefined, + mgmt_gateway: str | None | UndefinedType = Undefined, + ipv6_mgmt_ip: str | None | UndefinedType = Undefined, + ipv6_mgmt_gateway: str | None | UndefinedType = Undefined, + mgmt_interface: str | None | UndefinedType = Undefined, + link_tracking: LinkTracking | UndefinedType = Undefined, + lacp_port_id_range: LacpPortIdRange | UndefinedType = Undefined, + always_configure_ip_routing: bool | UndefinedType = Undefined, + raw_eos_cli: str | None | UndefinedType = Undefined, + structured_config: StructuredConfig | UndefinedType = Undefined, + uplink_type: Literal["p2p", "port-channel", "p2p-vrfs", "lan"] | None | UndefinedType = Undefined, + uplink_ipv4_pool: str | None | UndefinedType = Undefined, + uplink_interfaces: UplinkInterfaces | UndefinedType = Undefined, + uplink_switch_interfaces: UplinkSwitchInterfaces | UndefinedType = Undefined, + uplink_switches: UplinkSwitches | UndefinedType = Undefined, + uplink_interface_speed: str | None | UndefinedType = Undefined, + 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 | UndefinedType = Undefined, + uplink_bfd: bool | UndefinedType = Undefined, + uplink_native_vlan: int | None | UndefinedType = Undefined, + uplink_ptp: UplinkPtp | UndefinedType = Undefined, + uplink_macsec: UplinkMacsec | UndefinedType = Undefined, + uplink_port_channel_id: int | None | UndefinedType = Undefined, + uplink_switch_port_channel_id: int | None | UndefinedType = Undefined, + uplink_structured_config: dict | UndefinedType = Undefined, + mlag_port_channel_structured_config: MlagPortChannelStructuredConfig | UndefinedType = Undefined, + mlag_peer_vlan_structured_config: MlagPeerVlanStructuredConfig | UndefinedType = Undefined, + mlag_peer_l3_vlan_structured_config: MlagPeerL3VlanStructuredConfig | UndefinedType = Undefined, + short_esi: str | None | UndefinedType = Undefined, + isis_system_id_prefix: str | None | UndefinedType = Undefined, + isis_maximum_paths: int | None | UndefinedType = Undefined, + is_type: Literal["level-1-2", "level-1", "level-2"] | None | UndefinedType = Undefined, + node_sid_base: int | UndefinedType = Undefined, + loopback_ipv4_pool: str | None | UndefinedType = Undefined, + loopback_ipv4_address: str | None | UndefinedType = Undefined, + vtep_loopback_ipv4_pool: str | None | UndefinedType = Undefined, + vtep_loopback_ipv4_address: str | None | UndefinedType = Undefined, + loopback_ipv4_offset: int | UndefinedType = Undefined, + loopback_ipv6_pool: str | None | UndefinedType = Undefined, + loopback_ipv6_offset: int | UndefinedType = Undefined, + vtep: bool | None | UndefinedType = Undefined, + vtep_loopback: str | None | UndefinedType = Undefined, + bgp_as: str | None | UndefinedType = Undefined, + bgp_defaults: BgpDefaults | UndefinedType = Undefined, + evpn_role: Literal["client", "server", "none"] | None | UndefinedType = Undefined, + evpn_route_servers: EvpnRouteServers | UndefinedType = Undefined, + evpn_services_l2_only: bool | UndefinedType = Undefined, + filter: Filter | UndefinedType = Undefined, + igmp_snooping_enabled: bool | None | UndefinedType = Undefined, + evpn_gateway: EvpnGateway | UndefinedType = Undefined, + ipvpn_gateway: IpvpnGateway | UndefinedType = Undefined, + mlag: bool | UndefinedType = Undefined, + mlag_dual_primary_detection: bool | UndefinedType = Undefined, + mlag_ibgp_origin_incomplete: bool | UndefinedType = Undefined, + mlag_interfaces: MlagInterfaces | UndefinedType = Undefined, + mlag_interfaces_speed: str | None | UndefinedType = Undefined, + mlag_peer_l3_vlan: int | UndefinedType = Undefined, + mlag_peer_l3_ipv4_pool: str | None | UndefinedType = Undefined, + mlag_peer_vlan: int | UndefinedType = Undefined, + mlag_peer_link_allowed_vlans: str | None | UndefinedType = Undefined, + mlag_peer_address_family: Literal["ipv4", "ipv6"] | UndefinedType = Undefined, + mlag_peer_ipv4_pool: str | None | UndefinedType = Undefined, + mlag_peer_ipv6_pool: str | None | UndefinedType = Undefined, + mlag_port_channel_id: int | None | UndefinedType = Undefined, + mlag_domain_id: str | None | UndefinedType = Undefined, + spanning_tree_mode: Literal["mstp", "rstp", "rapid-pvst", "none"] | None | UndefinedType = Undefined, + spanning_tree_priority: int | UndefinedType = Undefined, + spanning_tree_root_super: bool | UndefinedType = Undefined, + virtual_router_mac_address: str | None | UndefinedType = Undefined, + inband_mgmt_interface: str | None | UndefinedType = Undefined, + inband_mgmt_vlan: int | UndefinedType = Undefined, + inband_mgmt_subnet: str | None | UndefinedType = Undefined, + inband_mgmt_ip: str | None | UndefinedType = Undefined, + inband_mgmt_gateway: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_address: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_subnet: str | None | UndefinedType = Undefined, + inband_mgmt_ipv6_gateway: str | None | UndefinedType = Undefined, + inband_mgmt_description: str | UndefinedType = Undefined, + inband_mgmt_vlan_name: str | UndefinedType = Undefined, + inband_mgmt_vrf: str | UndefinedType = Undefined, + inband_mgmt_mtu: int | UndefinedType = Undefined, + inband_ztp: bool | UndefinedType = Undefined, + inband_ztp_lacp_fallback_delay: int | UndefinedType = Undefined, + mpls_overlay_role: Literal["client", "server", "none"] | None | UndefinedType = Undefined, + overlay_address_families: OverlayAddressFamilies | UndefinedType = Undefined, + mpls_route_reflectors: MplsRouteReflectors | UndefinedType = Undefined, + bgp_cluster_id: str | None | UndefinedType = Undefined, + ptp: Ptp | UndefinedType = Undefined, + wan_role: Literal["client", "server"] | None | UndefinedType = Undefined, + cv_pathfinder_transit_mode: Literal["region", "zone"] | None | UndefinedType = Undefined, + cv_pathfinder_region: str | None | UndefinedType = Undefined, + cv_pathfinder_site: str | None | UndefinedType = Undefined, + wan_ha: WanHa | UndefinedType = Undefined, + dps_mss_ipv4: str | UndefinedType = Undefined, + l3_interfaces: L3Interfaces | UndefinedType = Undefined, + data_plane_cpu_allocation_max: int | None | UndefinedType = Undefined, + flow_tracker_type: Literal["sampled", "hardware"] | None | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NodesItem. + + + Subclass of AvdModel. + + Args: + name: The Node Name is used as "hostname". + downlink_pools: + IPv4 pools used for links to downlink switches. Set this on the parent switch. Cannot be combined + with `uplink_ipv4_pool` set on the downlink switch. + + Subclass of AvdList with `DownlinkPoolsItem` + items. + id: Unique identifier used for IP addressing and other algorithms. + platform: Arista platform family. + mac_address: Leverage to document management interface mac address. + system_mac_address: + System MAC Address in this following format: "xx:xx:xx:xx:xx:xx". + Set to the same MAC address as + available in "show version" on the device. + "system_mac_address" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + serial_number: + Set to the Serial Number of the device. + Only used for documentation purpose in the fabric + documentation and part of the structured_config. + "serial_number" can also be set directly as a + hostvar. + If both are set, the setting under node type settings takes precedence. + rack: Rack that the switch is located in (only used in snmp_settings location). + mgmt_ip: Node management interface IPv4 address. + mgmt_gateway: + This key sets the management gateway for the device. It takes precedence over the global + `mgmt_gateway`. + ipv6_mgmt_ip: Node management interface IPv6 address. + ipv6_mgmt_gateway: + This key sets the ipv6 management gateway for the device. It takes precedence over the global + `ipv6_mgmt_gateway`. + mgmt_interface: + Management Interface Name. + Default -> platform_management_interface -> mgmt_interface -> + "Management1". + link_tracking: + This configures the Link Tracking Group on a switch as well as adds the p2p-uplinks of the switch as + the upstream interfaces. + Useful in EVPN multhoming designs. + + + Subclass of AvdModel. + lacp_port_id_range: + This will generate the "lacp port-id range", "begin" and "end" values based on node "id" and the + number of nodes in the "node_group". + Unique LACP port-id ranges are recommended for EVPN Multihoming + designs. + + + Subclass of AvdModel. + always_configure_ip_routing: + Force configuration of "ip routing" even on L2 devices. + Use this to retain behavior of AVD versions + below 4.0.0. + raw_eos_cli: EOS CLI rendered directly on the root level of the final EOS configuration. + structured_config: + Custom structured config for eos_cli_config_gen. + + Subclass of AvdModel. + uplink_type: + Override the default `uplink_type` set at the `node_type_key` level. + `uplink_type` must be "p2p" if + `vtep` or `underlay_router` is true for the `node_type_key` definition. + uplink_ipv4_pool: IPv4 subnet to use to connect to uplink switches. + uplink_interfaces: + Local uplink interfaces. + Each list item supports range syntax that can be expanded into a list of + interfaces. + If uplink_interfaces is not defined, platform-specific defaults (defined under + default_interfaces) will be used instead. + Please note that default_interfaces are not defined by + default, you should define these yourself. + + + Subclass of AvdList with `str` items. + uplink_switch_interfaces: + Interfaces located on uplink switches. + + Subclass of AvdList with `str` items. + uplink_switches: Subclass of AvdList with `str` items. + uplink_interface_speed: + Set point-to-Point interface speed and will apply to uplink interfaces on both ends. + (Uplink switch + interface speed can be overridden with `uplink_switch_interface_speed`). + Speed should be set in the + format `` or `forced ` or `auto `. + uplink_switch_interface_speed: + 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: Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting. + max_uplink_switches: + 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: + 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: Enable bfd on uplink interfaces. + uplink_native_vlan: + 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: + Enable PTP on all infrastructure links. + + Subclass of AvdModel. + uplink_macsec: + Enable MacSec on all uplinks. + + Subclass of AvdModel. + uplink_port_channel_id: + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink Port-channel + ID will be set to the number of the lowest member interface defined under `uplink_interfaces`. + For + example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ Eth11/1, Eth22/1 ] -> ID 111 + For + MLAG port-channels ID will be based on the lowest member interface on the first MLAG switch. + This + option overrides the default behavior and statically sets the local Port-channel ID. + Note! Make sure + the ID is unique and does not overlap with autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between 1 and 2000 and both MLAG switches must have the same + value. + uplink_switch_port_channel_id: + Only applicable for L2 switches with `uplink_type: port-channel`. + By default the uplink switch Port- + channel ID will be set to the number of the first interface defined under + `uplink_switch_interfaces`. + For example: + member ports [ Eth22, Eth23 ] -> ID 22 + member ports [ + Eth11/1, Eth22/1 ] -> ID 111 + For MLAG port-channels ID will be based on the lowest member interface + on the first MLAG switch. + This option overrides the default behavior and statically sets the Port- + channel ID on the uplink switch. + Note! Make sure the ID is unique and does not overlap with + autogenerated Port-channel IDs in the Network Services. + Note! For MLAG pairs the ID must be between + 1 and 2000 and both MLAG switches must have the same value. + uplink_structured_config: + Custom structured config applied to "uplink_interfaces", and "uplink_switch_interfaces". + When + uplink_type == "p2p", custom structured config added under ethernet_interfaces.[name=] + for eos_cli_config_gen overrides the settings on the ethernet interface level. + When uplink_type == + "port-channel", custom structured config added under port_channel_interfaces.[name=] for + eos_cli_config_gen overrides the settings on the port-channel interface level. + "uplink_structured_config" is applied after "structured_config", so it can override + "structured_config" defined on node-level. + Note! The content of this dictionary is _not_ validated + by the schema, since it can be either ethernet_interfaces or port_channel_interfaces. + mlag_port_channel_structured_config: + Custom structured config applied to MLAG peer link port-channel id. + Added under + port_channel_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the + port-channel interface level. + "mlag_port_channel_structured_config" is applied after + "structured_config", so it can override "structured_config" defined on node-level. + + + Subclass of + AvdModel. + mlag_peer_vlan_structured_config: + Custom structured config applied to MLAG Peer Link (control link) SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_vlan_structured_config" is applied after "structured_config", so it can + override "structured_config" defined on node-level. + + + Subclass of AvdModel. + mlag_peer_l3_vlan_structured_config: + Custom structured config applied to MLAG underlay L3 peering SVI interface id. + Added under + vlan_interfaces.[name=] for eos_cli_config_gen. + Overrides the settings on the vlan + interface level. + "mlag_peer_l3_vlan_structured_config" is applied after "structured_config", so it + can override "structured_config" defined on node-level. + + + Subclass of AvdModel. + short_esi: + short_esi only valid for l2leaf devices using port-channel uplink. + Setting short_esi to "auto" + generates the short_esi automatically using a hash of configuration elements. + < 0000:0000:0000 | + auto >. + isis_system_id_prefix: (4.4 hexadecimal). + isis_maximum_paths: Number of path to configure in ECMP for ISIS. + is_type: Overrides `isis_default_is_type`. + node_sid_base: Node-SID base for isis-sr underlay variants. Combined with node id to generate ISIS-SR node-SID. + loopback_ipv4_pool: IPv4 subnet for Loopback0 allocation. + loopback_ipv4_address: + IPv4 address without mask for Loopback0. + When set, it takes precedence over `loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not catch duplicates. + vtep_loopback_ipv4_pool: IPv4 subnet for VTEP-Loopback allocation. + vtep_loopback_ipv4_address: + IPv4 address without mask for VTEP-Loopback. + When set, it takes precedence over + `vtep_loopback_ipv4_pool`. + Note: AVD does not check for validity of the IPv4 address and does not + catch duplicates. + loopback_ipv4_offset: + Offset all assigned loopback IP addresses. + Required when the < loopback_ipv4_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid over-lapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv4_offset: < total # spine switches > or vice versa. + loopback_ipv6_pool: IPv6 subnet for Loopback0 allocation. + loopback_ipv6_offset: + Offset all assigned loopback IPv6 addresses. + Required when the < loopback_ipv6_pool > is same for 2 + different node_types (like spine and l3leaf) to avoid overlapping IPs. + For example, set the minimum + offset l3leaf.defaults.loopback_ipv6_offset: < total # spine switches > or vice versa. + vtep: + Node is configured as a VTEP when applicable based on 'overlay_routing_protocol'. + Overrides VTEP + setting inherited from node_type_keys. + vtep_loopback: Set VXLAN source interface. + bgp_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + For asdot notation in + YAML inputs, the value must be put in quotes, to prevent it from being interpreted as a float + number. + Required with eBGP. + bgp_defaults: + List of EOS commands to apply to BGP daemon. + + Subclass of AvdList with `str` items. + evpn_role: + Acting role in EVPN control plane. + Default is set in node_type definition from node_type_keys. + evpn_route_servers: + List of nodes acting as EVPN Route-Servers / Route-Reflectors. + + Subclass of AvdList with `str` + items. + evpn_services_l2_only: + Possibility to prevent configuration of Tenant VRFs and SVIs. + Override node definition + "network_services_l3" from node_type_keys. + This allows support for centralized routing. + filter: + Filter L3 and L2 network services based on tenant and tags (and operation filter). + If filter is not + defined it will default to all. + + + Subclass of AvdModel. + igmp_snooping_enabled: Activate or deactivate IGMP snooping on device level. + evpn_gateway: + Node is acting as EVPN Multi-Domain Gateway. + New BGP peer-group is generated between EVPN GWs in + different domains or between GWs and Route Servers. + Name can be changed under + "bgp_peer_groups.evpn_overlay_core" variable. + L3 rechability for different EVPN GWs must be already + in place, it is recommended to use DCI & L3 Edge if Route Servers and GWs are not defined under the + same Ansible inventory. + + + Subclass of AvdModel. + ipvpn_gateway: + Node is acting as IP-VPN Gateway for EVPN to MPLS-IP-VPN Interworking. The BGP peer group used for + this is "bgp_peer_groups.ipvpn_gateway_peers". + L3 Reachability is required for this to work, the + preferred method to establish underlay connectivity is to use core_interfaces. + + + Subclass of + AvdModel. + mlag: Enable / Disable auto MLAG, when two nodes are defined in node group. + mlag_dual_primary_detection: Enable / Disable MLAG dual primary detection. + mlag_ibgp_origin_incomplete: + Set origin of routes received from MLAG iBGP peer to incomplete. + The purpose is to optimize routing + for leaf loopbacks from spine perspective and + avoid suboptimal routing via peerlink for control + plane traffic. + mlag_interfaces: + Each list item supports range syntax that can be expanded into a list of interfaces. + Required when + MLAG leafs are present in the topology. + + + Subclass of AvdList with `str` items. + mlag_interfaces_speed: + Set MLAG interface speed. + Speed should be set in the format `` or `forced + ` or `auto `. + mlag_peer_l3_vlan: + Underlay L3 peering SVI interface id. + If set to 0 or the same vlan as mlag_peer_vlan, the + mlag_peer_vlan will be used for L3 peering. + mlag_peer_l3_ipv4_pool: + IP address pool used for MLAG underlay L3 peering. IP is derived from the node id. + Required when + MLAG leafs present in topology and they are using a separate L3 peering VLAN. + mlag_peer_vlan: MLAG Peer Link (control link) SVI interface id. + mlag_peer_link_allowed_vlans: mlag_peer_link_allowed_vlans + mlag_peer_address_family: + IP address family used to establish MLAG Peer Link (control link). + `ipv6` requires EOS version + 4.31.1F or higher. + Note: `ipv6` is not supported in combination with a common MLAG peer link VLAN + (ex. `mlag_peer_l3_vlan` set to 4094). + mlag_peer_ipv4_pool: + IPv4 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv4` (default). + mlag_peer_ipv6_pool: + IPv6 address pool used for MLAG Peer Link (control link). IP is derived from the node id. + Required + for MLAG leafs when `mlag_peer_address_family` is `ipv6`. + mlag_port_channel_id: + If not set, the mlag port-channel id is generated based on the digits of the first interface present + in 'mlag_interfaces'. + Valid port-channel id numbers are < 1-2000 > for EOS < 4.25.0F and < 1 - + 999999 > for EOS >= 4.25.0F. + mlag_domain_id: MLAG Domain ID. If not set the node group name (Set with "group" key) will be used. + spanning_tree_mode: spanning_tree_mode + spanning_tree_priority: + Spanning-tree priority configured for the selected mode. + For `rapid-pvst` the priority can also be + set per VLAN under network services. + spanning_tree_root_super: spanning_tree_root_super + virtual_router_mac_address: Virtual router mac address for anycast gateway. + inband_mgmt_interface: + Pointer to interface used for inband management. + All configuration must be done using other data + models like network services or structured_config. + 'inband_mgmt_interface' is only used to refer to + this interface as source in various management protocol settings (future feature). + + On L2 switches, + this defaults to Vlan if either 'inband_mgmt_subnet' or 'inband_mgmt_ip' is set. + inband_mgmt_vlan: + VLAN number used for inband management on L2 switches (switches using port-channel trunks as + uplinks). + When using 'inband_mgmt_subnet' the VLAN and SVIs will be created automatically on this + switch as well as all 'uplink_switches'. + When using 'inband_mgmt_ip' the VLAN and SVI will only be + created on this device and added to uplink trunk. The VLAN and SVI on the parent switches must be + created using network services data models. + inband_mgmt_subnet: + Optional IP subnet assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ip virtual-router" and host-route injection based on + ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + + 3 + + GW on l2leafs : + 1 + Assign range larger than total l2leafs + 5 + Setting is ignored if 'inband_mgmt_ip' is set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + inband_mgmt_ip: + IP address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_subnet', hence all behavior of 'inband_mgmt_subnet' is removed. + + If this is set the + VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN and SVI on + the parent switches must be created using network services data models. + + This setting is applicable + to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_gateway: + Default gateway configured in the 'inband_mgmt_vrf' when using 'inband_mgmt_ip'. Otherwise gateway + is derived from 'inband_mgmt_subnet' if set. + + This setting is applicable to L2 switches (switches + using port-channel trunks as uplinks). + inband_mgmt_ipv6_address: + IPv6 address assigned to the inband management interface set with 'inband_mgmt_vlan'. + This overrides + 'inband_mgmt_ipv6_subnet', hence the configuration of 'inband_mgmt_ipv6_subnet' is ignored. + + If this + is set the VLAN and SVI will only be created on the L2 switch and added to uplink trunk. + The VLAN + and SVI on the parent switches must be created using network services data models. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_ipv6_subnet: + Optional IPv6 prefix assigned to inband management SVIs on L2 switches (switches using port-channels + as uplinks). + Parent l3leafs will have SVI with "ipv6 virtual-router" and host-route injection based + on ARP. + This allows all l3leafs to reuse the same subnet across multiple racks without VXLAN + extension. + SVI IP address will be assigned as follows: + virtual-router: + 1 + l3leaf A : + + 2 (same IP on all l3leaf A) + l3leaf B : + 3 (same IP on all l3leaf B) + l2leafs : + 3 + + GW on l2leafs : + 1 + Assign range larger than + total l2leafs + 5 + + Setting is ignored if 'inband_mgmt_ipv6_address' is set. + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_ipv6_gateway: + Default gateway configured in the 'inband_mgmt_vrf'. + Used when `inband_mgmt_ipv6_address` is set. + Ignored when 'inband_mgmt_ipv6_subnet' is set (first IP in subnet used as gateway). + + This setting is + applicable to L2 switches (switches using port-channel trunks as uplinks). + inband_mgmt_description: + Description configured on the Inband Management SVI. + + This setting is only applied on the devices + where it is set, it does not automatically affect any parent/child devices configuration, so it must + be set on each applicable node/node-group/node-type as needed. + inband_mgmt_vlan_name: + Name configured on the Inband Management VLAN. + This setting is only applied on the devices where it + is set, it does not automatically affect any parent/child devices configuration, so it must be set + on each applicable node/node-group/node-type as needed. + inband_mgmt_vrf: + VRF configured on the Inband Management Interface. + The VRF is created if not already created by + other means. + This setting is only applied on the devices where it is set, it does not automatically + affect any parent/child devices configuration, so it must be set on each applicable node/node- + group/node-type as needed. + inband_mgmt_mtu: + MTU configured on the Inband Management Interface. + This setting is only applied on the devices where + it is set, it does not automatically affect any parent/child devices configuration, so it must be + set on each applicable node/node-group/node-type as needed. + inband_ztp: + Enable to configure upstream device with proper configuration to allow downstream devices to be + Zero-Touch-Provisioned over the uplink interfaces. + For L2 devices this setting also requires that + the `inband_mgmt_vlan` is set for the node. + + PREVIEW: Support for L3 devices is marked as "preview", + meaning the data models or generated configuration can change at any time. + inband_ztp_lacp_fallback_delay: + Set the LACP fallback timeout of the upstream device's port-channel towards the downstream inband + ZTP node. + This setting also requires that `inband_ztp` is set for the node. + mpls_overlay_role: + Set the default mpls overlay role. + Acting role in overlay control plane. + overlay_address_families: + Set the default overlay address families. + + + Subclass of AvdList with `str` items. + mpls_route_reflectors: + List of inventory hostname acting as MPLS route-reflectors. + + Subclass of AvdList with `str` items. + bgp_cluster_id: Set BGP cluster id. + ptp: Subclass of AvdModel. + wan_role: + Override the default WAN role. + + This is used both for AutoVPN and Pathfinder designs. + That means if + `wan_mode` root key is set to `autovpn` or `cv-pathfinder`. + `server` indicates that the router is a + route-reflector. + + Only supported if `overlay_routing_protocol` is set to `ibgp`. + cv_pathfinder_transit_mode: + Configure the transit mode for a WAN client for CV Pathfinder designs + only when the `wan_mode` root + key is set to `cv_pathfinder`. + + 'zone' is currently not supported. + cv_pathfinder_region: + The CV Pathfinder region name. + This key is required for WAN routers but optional for pathfinders. + The region name must be defined under 'cv_pathfinder_regions'. + cv_pathfinder_site: + The CV Pathfinder site name. + This key is required for WAN routers but optional for pathfinders. + For + WAN routers and pathfinders with `cv_pathfinder_region`, the site name must be defined for the + relevant region under 'cv_pathfinder_regions'. + For pathfinders without `cv_pathfinder_region` set, + the site must be defined under `cv_pathfinder_global_sites`. + wan_ha: + PREVIEW: This key is currently not supported + + The key is supported only if `wan_mode` == `cv- + pathfinder`. + AutoVPN support is still to be determined. + + Maximum 2 devices supported by group for + HA. + + Subclass of AvdModel. + dps_mss_ipv4: IPv4 MSS value configured under "router path-selection" on WAN Devices. + l3_interfaces: + L3 Interfaces to configure on the node. + Used to define the node for WAN interfaces when + `wan_carrier` is set. + + Subclass of AvdIndexedList with `L3InterfacesItem` items. Primary key is + `name` (`str`). + data_plane_cpu_allocation_max: + Set the maximum number of CPU used for the data plane. + This setting is useful on virtual Route + Reflectors and Pathfinders where more CPU cores should be allocated for control plane. + flow_tracker_type: + Set the flow tracker type. + Override the `default_flow_tracker_type`` set at the `node_type_key` + level. + `default_flow_tracker_type` default value is `sampled`. + _custom_data: _custom_data + + """ + + class Nodes(AvdIndexedList[str, NodesItem]): + """Subclass of AvdIndexedList with `NodesItem` items. Primary key is `name` (`str`).""" + + _primary_key: ClassVar[str] = "name" + + Nodes._item_type = NodesItem + + _fields: ClassVar[dict] = { + "defaults": {"type": Defaults}, + "node_groups": {"type": NodeGroups}, + "nodes": {"type": Nodes}, + "_custom_data": {"type": dict}, + } + defaults: Defaults + """ + Define variables for all nodes of this type. + + Subclass of AvdModel. + """ + node_groups: NodeGroups + """ + Define variables related to all nodes part of this group. + + Subclass of AvdIndexedList with + `NodeGroupsItem` items. Primary key is `group` (`str`). + """ + nodes: Nodes + """ + Define variables per node. + + Subclass of AvdIndexedList with `NodesItem` items. Primary key is `name` + (`str`). + """ + _custom_data: dict[str, Any] + + if TYPE_CHECKING: + + def __init__( + self, + *, + defaults: Defaults | UndefinedType = Undefined, + node_groups: NodeGroups | UndefinedType = Undefined, + nodes: Nodes | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + ) -> None: + """ + NodeTypes. + + + Subclass of AvdModel. + + Args: + defaults: + Define variables for all nodes of this type. + + Subclass of AvdModel. + node_groups: + Define variables related to all nodes part of this group. + + Subclass of AvdIndexedList with + `NodeGroupsItem` items. Primary key is `group` (`str`). + nodes: + Define variables per node. + + Subclass of AvdIndexedList with `NodesItem` items. Primary key is `name` + (`str`). + _custom_data: _custom_data + + """ + + _fields: ClassVar[dict] = {"key": {"type": str}, "value": {"type": NodeTypes}} + _field_to_key_map: ClassVar[dict] = {"value": "node_type_keys_key"} + _key_to_field_map: ClassVar[dict] = {"node_type_keys_key": "value"} + key: str + """Key used as dynamic key""" + value: NodeTypes + """Value of dynamic key""" + + if TYPE_CHECKING: + + def __init__(self, *, key: str | UndefinedType = Undefined, value: NodeTypes | UndefinedType = Undefined) -> None: + """ + DynamicNodeTypesItem. + + + Args: + key: Key used as dynamic key + value: Value of dynamic key + + """ + + class DynamicNodeTypes(AvdIndexedList[str, DynamicNodeTypesItem]): + _primary_key: ClassVar[str] = "key" + + DynamicNodeTypes._item_type = DynamicNodeTypesItem + + _dynamic_key_maps: ClassVar[tuple[dict, ...]] = ( + {"dynamic_keys_path": "connected_endpoints_keys.key", "model_key": "connected_endpoints"}, + {"dynamic_keys_path": "custom_node_type_keys.key", "model_key": "custom_node_types"}, + {"dynamic_keys_path": "network_services_keys.name", "model_key": "network_services"}, + {"dynamic_keys_path": "node_type_keys.key", "model_key": "node_types"}, + ) + _fields: ClassVar[dict] = { + "connected_endpoints": {"type": DynamicConnectedEndpoints}, + "custom_node_types": {"type": DynamicCustomNodeTypes}, + "network_services": {"type": DynamicNetworkServices}, + "node_types": {"type": DynamicNodeTypes}, + } + connected_endpoints: DynamicConnectedEndpoints + """Collection of dynamic 'connected_endpoints'.""" + custom_node_types: DynamicCustomNodeTypes + """Collection of dynamic 'custom_node_types'.""" + network_services: DynamicNetworkServices + """Collection of dynamic 'network_services'.""" + node_types: DynamicNodeTypes + """Collection of dynamic 'node_types'.""" + + if TYPE_CHECKING: + + def __init__( + self, + *, + connected_endpoints: DynamicConnectedEndpoints | UndefinedType = Undefined, + custom_node_types: DynamicCustomNodeTypes | UndefinedType = Undefined, + network_services: DynamicNetworkServices | UndefinedType = Undefined, + node_types: DynamicNodeTypes | UndefinedType = Undefined, + ) -> None: + """ + _DynamicKeys. + + + Data models for dynamic keys. + + Args: + connected_endpoints: Collection of dynamic 'connected_endpoints'. + custom_node_types: Collection of dynamic 'custom_node_types'. + network_services: Collection of dynamic 'network_services'. + node_types: Collection of dynamic 'node_types'. + + """ + + _fields: ClassVar[dict] = { + "application_classification": {"type": ApplicationClassification}, + "avd_data_validation_mode": {"type": str, "default": "error"}, + "avd_eos_designs_debug": {"type": bool, "default": False}, + "avd_eos_designs_structured_config": {"type": bool, "default": True}, + "avd_eos_designs_unset_facts": {"type": bool, "default": True}, + "bfd_multihop": {"type": BfdMultihop, "default": lambda cls: coerce_type({"interval": 300, "min_rx": 300, "multiplier": 3}, target_type=cls)}, + "bgp_as": {"type": str}, + "bgp_default_ipv4_unicast": {"type": bool, "default": False}, + "bgp_distance": {"type": BgpDistance}, + "bgp_ecmp": {"type": int}, + "bgp_graceful_restart": {"type": BgpGracefulRestart}, + "bgp_maximum_paths": {"type": int}, + "bgp_mesh_pes": {"type": bool, "default": False}, + "bgp_peer_groups": {"type": BgpPeerGroups}, + "bgp_update_wait_install": {"type": bool, "default": True}, + "bgp_update_wait_for_convergence": {"type": bool, "default": False}, + "connected_endpoints_keys": { + "type": ConnectedEndpointsKeys, + "default": lambda cls: coerce_type( + [ + {"key": "servers", "type": "server", "description": "Server"}, + {"key": "firewalls", "type": "firewall", "description": "Firewall"}, + {"key": "routers", "type": "router", "description": "Router"}, + {"key": "load_balancers", "type": "load_balancer", "description": "Load Balancer"}, + {"key": "storage_arrays", "type": "storage_array", "description": "Storage Array"}, + {"key": "cpes", "type": "cpe", "description": "CPE"}, + {"key": "workstations", "type": "workstation", "description": "Workstation"}, + {"key": "access_points", "type": "access_point", "description": "Access Point"}, + {"key": "phones", "type": "phone", "description": "Phone"}, + {"key": "printers", "type": "printer", "description": "Printer"}, + {"key": "cameras", "type": "camera", "description": "Camera"}, + {"key": "generic_devices", "type": "generic_device", "description": "Generic Device"}, + ], + target_type=cls, + ), + }, + "core_interfaces": {"type": CoreInterfaces}, + "custom_structured_configuration_list_merge": {"type": str, "default": "append_rp"}, + "custom_structured_configuration_prefix": { + "type": CustomStructuredConfigurationPrefix, + "default": lambda cls: coerce_type(["custom_structured_configuration_"], target_type=cls), + }, + "cv_pathfinder_global_sites": {"type": CvPathfinderGlobalSites}, + "cv_pathfinder_internet_exit_policies": {"type": CvPathfinderInternetExitPolicies}, + "cv_pathfinder_regions": {"type": CvPathfinderRegions}, + "cv_server": {"type": str}, + "cv_tags_topology_type": {"type": str}, + "cv_token": {"type": str}, + "cv_topology": {"type": CvTopology}, + "cvp_ingestauth_key": {"type": str}, + "cvp_instance_ips": {"type": CvpInstanceIps}, + "cvp_token_file": {"type": str}, + "dc_name": {"type": str}, + "default_connected_endpoints_description": {"type": str, "default": "{endpoint_type!u}_{endpoint}{endpoint_port?<_}"}, + "default_connected_endpoints_port_channel_description": {"type": str, "default": "{endpoint_type!u}_{endpoint}{endpoint_port_channel?<_}"}, + "default_igmp_snooping_enabled": {"type": bool, "default": True}, + "default_interface_mtu": {"type": int}, + "default_interfaces": {"type": DefaultInterfaces}, + "default_mgmt_method": {"type": str, "default": "oob"}, + "default_network_ports_description": {"type": str, "default": "{endpoint?}"}, + "default_network_ports_port_channel_description": {"type": str, "default": "{endpoint?}{endpoint_port_channel?<_}"}, + "default_node_types": {"type": DefaultNodeTypes}, + "default_underlay_p2p_ethernet_description": {"type": str, "default": "P2P_{peer}_{peer_interface}{vrf?<_VRF_}"}, + "default_underlay_p2p_port_channel_description": {"type": str, "default": "P2P_{peer}_{peer_interface}"}, + "default_vrf_diag_loopback_description": {"type": str, "default": "DIAG_VRF_{vrf}"}, + "design": {"type": Design}, + "enable_trunk_groups": {"type": bool, "default": False}, + "eos_designs_custom_templates": {"type": EosDesignsCustomTemplates}, + "eos_designs_documentation": {"type": EosDesignsDocumentation}, + "event_handlers": {"type": EventHandlers}, + "evpn_ebgp_gateway_inter_domain": {"type": bool}, + "evpn_ebgp_gateway_multihop": {"type": int, "default": 15}, + "evpn_ebgp_multihop": {"type": int, "default": 3}, + "evpn_hostflap_detection": {"type": EvpnHostflapDetection}, + "evpn_import_pruning": {"type": bool, "default": False}, + "evpn_multicast": {"type": bool, "default": False}, + "evpn_overlay_bgp_rtc": {"type": bool, "default": False}, + "evpn_prevent_readvertise_to_server": {"type": bool, "default": False}, + "evpn_short_esi_prefix": {"type": str, "default": "0000:0000:"}, + "evpn_vlan_aware_bundles": {"type": bool, "default": False}, + "evpn_vlan_bundles": {"type": EvpnVlanBundles}, + "fabric_evpn_encapsulation": {"type": str}, + "fabric_flow_tracking": {"type": FabricFlowTracking}, + "fabric_ip_addressing": {"type": FabricIpAddressing}, + "fabric_name": {"type": str}, + "fabric_sflow": {"type": FabricSflow}, + "flow_tracking_settings": {"type": FlowTrackingSettings}, + "generate_cv_tags": {"type": GenerateCvTags}, + "hardware_counters": {"type": HardwareCounters}, + "internal_vlan_order": { + "type": InternalVlanOrder, + "default": lambda cls: coerce_type({"allocation": "ascending", "range": {"beginning": 1006, "ending": 1199}}, target_type=cls), + }, + "ipv4_acls": {"type": Ipv4Acls}, + "ipv4_prefix_list_catalog": {"type": Ipv4PrefixListCatalog}, + "ipv6_mgmt_destination_networks": {"type": Ipv6MgmtDestinationNetworks}, + "ipv6_mgmt_gateway": {"type": str}, + "is_deployed": {"type": bool, "default": True}, + "isis_advertise_passive_only": {"type": bool, "default": False}, + "isis_area_id": {"type": str, "default": "49.0001"}, + "isis_default_circuit_type": {"type": str, "default": "level-2"}, + "isis_default_is_type": {"type": str, "default": "level-2"}, + "isis_default_metric": {"type": int, "default": 50}, + "isis_maximum_paths": {"type": int, "default": 4}, + "isis_system_id_format": {"type": str, "default": "underlay_loopback"}, + "isis_ti_lfa": {"type": IsisTiLfa}, + "l3_edge": {"type": L3Edge}, + "l3_interface_profiles": {"type": L3InterfaceProfiles}, + "local_users": {"type": LocalUsers}, + "mac_address_table": {"type": MacAddressTable}, + "management_eapi": {"type": ManagementEapi}, + "mgmt_destination_networks": {"type": MgmtDestinationNetworks}, + "mgmt_gateway": {"type": str}, + "mgmt_interface": {"type": str, "default": "Management1"}, + "mgmt_interface_description": {"type": str, "default": "OOB_MANAGEMENT"}, + "mgmt_interface_vrf": {"type": str, "default": "MGMT"}, + "mgmt_vrf_routing": {"type": bool, "default": False}, + "mlag_bgp_peer_description": {"type": str, "default": "{mlag_peer}_{peer_interface}"}, + "mlag_bgp_peer_group_description": {"type": str, "default": "{mlag_peer}"}, + "mlag_ibgp_peering_vrfs": {"type": MlagIbgpPeeringVrfs}, + "mlag_member_description": {"type": str, "default": "MLAG_{mlag_peer}_{peer_interface}"}, + "mlag_on_orphan_port_channel_downlink": {"type": bool, "default": False}, + "mlag_peer_l3_svi_description": {"type": str, "default": "MLAG_L3"}, + "mlag_peer_l3_vlan_name": {"type": str, "default": "MLAG_L3"}, + "mlag_peer_l3_vrf_svi_description": {"type": str, "default": "MLAG_L3_VRF_{vrf}"}, + "mlag_peer_l3_vrf_vlan_name": {"type": str, "default": "MLAG_L3_VRF_{vrf}"}, + "mlag_peer_svi_description": {"type": str, "default": "MLAG"}, + "mlag_peer_vlan_name": {"type": str, "default": "MLAG"}, + "mlag_port_channel_description": {"type": str, "default": "MLAG_{mlag_peer}_{peer_interface}"}, + "name_servers": {"type": NameServers}, + "network_ports": {"type": NetworkPorts}, + "network_services_keys": {"type": NetworkServicesKeys, "default": lambda cls: coerce_type([{"name": "tenants"}], target_type=cls)}, + "custom_node_type_keys": {"type": CustomNodeTypeKeys}, + "node_type_keys": {"type": NodeTypeKeys}, + "ntp_settings": {"type": NtpSettings}, + "only_local_vlan_trunk_groups": {"type": bool, "default": False}, + "overlay_bgp_peer_description": {"type": str, "default": "{peer}{peer_interface?<_}"}, + "overlay_cvx_servers": {"type": OverlayCvxServers}, + "overlay_her_flood_list_per_vni": {"type": bool, "default": False}, + "overlay_her_flood_list_scope": {"type": str, "default": "fabric"}, + "overlay_loopback_description": {"type": str}, + "overlay_mlag_rfc5549": {"type": bool, "default": False}, + "overlay_rd_type": {"type": OverlayRdType}, + "overlay_routing_protocol": {"type": str}, + "overlay_routing_protocol_address_family": {"type": str, "default": "ipv4"}, + "overlay_rt_type": {"type": OverlayRtType}, + "p2p_uplinks_mtu": {"type": int, "default": 9214}, + "p2p_uplinks_qos_profile": {"type": str}, + "custom_platform_settings": {"type": CustomPlatformSettings}, + "platform_settings": { + "type": PlatformSettings, + "default": lambda cls: coerce_type( + [ + {"platforms": ["default"], "feature_support": {"queue_monitor_length_notify": False}, "reload_delay": {"mlag": 300, "non_mlag": 330}}, + { + "platforms": ["7050X3"], + "feature_support": {"queue_monitor_length_notify": False}, + "reload_delay": {"mlag": 300, "non_mlag": 330}, + "trident_forwarding_table_partition": "flexible exact-match 16384 l2-shared 98304 l3-shared 131072", + }, + { + "platforms": ["720XP"], + "feature_support": {"poe": True, "queue_monitor_length_notify": False}, + "reload_delay": {"mlag": 300, "non_mlag": 330}, + "trident_forwarding_table_partition": "flexible exact-match 16000 l2-shared 18000 l3-shared 22000", + }, + { + "platforms": ["750", "755", "758"], + "management_interface": "Management0", + "feature_support": {"poe": True, "queue_monitor_length_notify": False}, + "reload_delay": {"mlag": 300, "non_mlag": 330}, + }, + { + "platforms": ["720DP", "722XP", "710P"], + "feature_support": {"poe": True, "queue_monitor_length_notify": False}, + "reload_delay": {"mlag": 300, "non_mlag": 330}, + }, + { + "platforms": ["7010TX"], + "feature_support": {"queue_monitor_length_notify": False, "per_interface_mtu": False}, + "reload_delay": {"mlag": 300, "non_mlag": 330}, + }, + { + "platforms": ["7280R", "7280R2", "7020R"], + "lag_hardware_only": True, + "reload_delay": {"mlag": 900, "non_mlag": 1020}, + "tcam_profile": "vxlan-routing", + }, + {"platforms": ["7280R3"], "reload_delay": {"mlag": 900, "non_mlag": 1020}, "tcam_profile": "vxlan-routing"}, + { + "platforms": ["7500R", "7500R2"], + "lag_hardware_only": True, + "management_interface": "Management0", + "reload_delay": {"mlag": 900, "non_mlag": 1020}, + "tcam_profile": "vxlan-routing", + }, + { + "platforms": ["7500R3", "7800R3"], + "management_interface": "Management0", + "reload_delay": {"mlag": 900, "non_mlag": 1020}, + "tcam_profile": "vxlan-routing", + }, + { + "platforms": ["7358X4"], + "management_interface": "Management1/1", + "reload_delay": {"mlag": 300, "non_mlag": 330}, + "feature_support": { + "queue_monitor_length_notify": False, + "interface_storm_control": True, + "bgp_update_wait_for_convergence": True, + "bgp_update_wait_install": False, + }, + }, + {"platforms": ["7368X4"], "management_interface": "Management0", "reload_delay": {"mlag": 300, "non_mlag": 330}}, + { + "platforms": ["7300X3"], + "management_interface": "Management0", + "reload_delay": {"mlag": 1200, "non_mlag": 1320}, + "trident_forwarding_table_partition": "flexible exact-match 16384 l2-shared 98304 l3-shared 131072", + }, + { + "platforms": ["VEOS", "VEOS-LAB", "vEOS", "vEOS-lab"], + "feature_support": { + "bgp_update_wait_for_convergence": False, + "bgp_update_wait_install": False, + "interface_storm_control": False, + "queue_monitor_length_notify": False, + }, + "reload_delay": {"mlag": 300, "non_mlag": 330}, + }, + { + "platforms": ["CEOS", "cEOS", "ceos", "cEOSLab"], + "feature_support": { + "bgp_update_wait_for_convergence": False, + "bgp_update_wait_install": False, + "interface_storm_control": False, + "queue_monitor_length_notify": False, + }, + "management_interface": "Management0", + "reload_delay": {"mlag": 300, "non_mlag": 330}, + }, + { + "platforms": ["AWE-5310", "AWE-5510", "AWE-7250R", "AWE-7230R"], + "feature_support": { + "bgp_update_wait_for_convergence": True, + "bgp_update_wait_install": False, + "interface_storm_control": False, + "queue_monitor_length_notify": False, + }, + "management_interface": "Management1/1", + "p2p_uplinks_mtu": 9194, + }, + { + "platforms": ["AWE-7220R"], + "feature_support": { + "bgp_update_wait_for_convergence": True, + "bgp_update_wait_install": False, + "interface_storm_control": False, + "queue_monitor_length_notify": False, + "poe": True, + }, + "management_interface": "Management1", + "p2p_uplinks_mtu": 9194, + }, + ], + target_type=cls, + ), + }, + "platform_speed_groups": {"type": PlatformSpeedGroups}, + "pod_name": {"type": str}, + "port_profiles": {"type": PortProfiles}, + "ptp_profiles": { + "type": PtpProfiles, + "default": lambda cls: coerce_type( + [ + { + "profile": "aes67-r16-2016", + "announce": {"interval": 0, "timeout": 3}, + "delay_req": -3, + "sync_message": {"interval": -3}, + "transport": "ipv4", + }, + { + "profile": "smpte2059-2", + "announce": {"interval": -2, "timeout": 3}, + "delay_req": -4, + "sync_message": {"interval": -4}, + "transport": "ipv4", + }, + {"profile": "aes67", "announce": {"interval": 2, "timeout": 3}, "delay_req": 0, "sync_message": {"interval": 0}, "transport": "ipv4"}, + ], + target_type=cls, + ), + }, + "ptp_settings": {"type": PtpSettings}, + "queue_monitor_length": {"type": QueueMonitorLength}, + "redundancy": {"type": Redundancy}, + "router_id_loopback_description": {"type": str, "default": "ROUTER_ID"}, + "serial_number": {"type": str}, + "sflow_settings": {"type": SflowSettings}, + "shutdown_bgp_towards_undeployed_peers": {"type": bool, "default": True}, + "shutdown_interfaces_towards_undeployed_peers": {"type": bool, "default": True}, + "snmp_settings": {"type": SnmpSettings}, + "source_interfaces": {"type": SourceInterfaces}, + "svi_profiles": {"type": SviProfiles}, + "system_mac_address": {"type": str}, + "terminattr_disable_aaa": {"type": bool, "default": False}, + "terminattr_ingestexclude": {"type": str, "default": "/Sysdb/cell/1/agent,/Sysdb/cell/2/agent"}, + "terminattr_ingestgrpcurl_port": {"type": int, "default": 9910}, + "terminattr_smashexcludes": {"type": str, "default": "ale,flexCounter,hardware,kni,pulse,strata"}, + "timezone": {"type": str}, + "trunk_groups": {"type": TrunkGroups}, + "type": {"type": str}, + "underlay_filter_peer_as": {"type": bool, "default": False}, + "underlay_filter_redistribute_connected": {"type": bool, "default": True}, + "underlay_ipv6": {"type": bool, "default": False}, + "underlay_isis_authentication_key": {"type": str}, + "underlay_isis_authentication_mode": {"type": str}, + "underlay_isis_bfd": {"type": bool, "default": False}, + "underlay_isis_instance_name": {"type": str}, + "underlay_l2_ethernet_description": {"type": str, "default": "L2_{peer}_{peer_interface}"}, + "underlay_l2_port_channel_description": {"type": str, "default": "L2_{peer_node_group_or_peer}_{peer_interface}"}, + "underlay_multicast": {"type": bool, "default": False}, + "underlay_multicast_anycast_rp": {"type": UnderlayMulticastAnycastRp}, + "underlay_multicast_rps": {"type": UnderlayMulticastRps}, + "underlay_ospf_area": {"type": str, "default": "0.0.0.0"}, + "underlay_ospf_authentication": {"type": UnderlayOspfAuthentication}, + "underlay_ospf_bfd_enable": {"type": bool, "default": False}, + "underlay_ospf_max_lsa": {"type": int, "default": 12000}, + "underlay_ospf_process_id": {"type": int, "default": 100}, + "underlay_rfc5549": {"type": bool, "default": False}, + "underlay_routing_protocol": {"type": str}, + "uplink_ptp": {"type": UplinkPtp}, + "use_cv_topology": {"type": bool}, + "use_router_general_for_router_id": {"type": bool, "default": False}, + "vtep_loopback_description": {"type": str, "default": "VXLAN_TUNNEL_SOURCE"}, + "vtep_vvtep_ip": {"type": str}, + "wan_carriers": {"type": WanCarriers}, + "wan_encapsulation": {"type": str, "default": "path-selection"}, + "wan_ha": {"type": WanHa}, + "wan_ipsec_profiles": {"type": WanIpsecProfiles}, + "wan_mode": {"type": str, "default": "cv-pathfinder"}, + "wan_path_groups": {"type": WanPathGroups}, + "wan_route_servers": {"type": WanRouteServers}, + "wan_stun_dtls_disable": {"type": bool, "default": False}, + "wan_stun_dtls_profile_name": {"type": str, "default": "STUN-DTLS"}, + "wan_virtual_topologies": {"type": WanVirtualTopologies}, + "zscaler_endpoints": {"type": ZscalerEndpoints}, + "_custom_data": {"type": dict}, + "_custom_structured_configurations": {"type": _CustomStructuredConfigurations}, + "_dynamic_keys": {"type": _DynamicKeys}, + } + _allow_other_keys: ClassVar[bool] = True + application_classification: ApplicationClassification + """ + Application traffic recognition configuration. + + Subclass of AvdModel. + """ + avd_data_validation_mode: Literal["error", "warning"] + """ + Validation Mode for AVD input data validation. + Input data validation will validate the input + variables according to the schema. + During validation, messages will generated with information about + the host(s) and key(s) which failed validation. + "error" will produce error messages and fail the + task. + "warning" will produce warning messages. + + Default value: `"error"` + """ + avd_eos_designs_debug: bool + """ + Dump all vars and facts per device after generating `avd_switch_facts`. + + Default value: `False` + """ + avd_eos_designs_structured_config: bool + """ + Generate structured configuration per device. + + Default value: `True` + """ + avd_eos_designs_unset_facts: bool + """ + Unset `avd_switch_facts` to gain a small performance improvement since Ansible needs to handle fewer + variables. + + Default value: `True` + """ + bfd_multihop: BfdMultihop + """ + BFD Multihop tuning. + + Subclass of AvdModel. + + Default value: `lambda cls: coerce_type({"interval": 300, "min_rx": 300, "multiplier": 3}, target_type=cls)` + """ + bgp_as: str | None + """ + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>" to use to configure + overlay when "overlay_routing_protocol" == ibgp. + For asdot notation in YAML inputs, the value must + be put in quotes, to prevent it from being interpreted as a float number. + """ + bgp_default_ipv4_unicast: bool + """ + Default activation of IPv4 unicast address-family on all IPv4 neighbors. + It is best practice to + disable activation. + + Default value: `False` + """ + bgp_distance: BgpDistance + """Subclass of AvdModel.""" + bgp_ecmp: int | None + """ + Maximum ECMP for BGP multi-path. + The default value is 4 except for WAN Routers where the default + value is unset (falls back to EOS default). + """ + bgp_graceful_restart: BgpGracefulRestart + """ + BGP graceful-restart allows a BGP speaker with separate control plane and data plane processing to + continue forwarding traffic during a BGP restart. + Its neighbors (receiving speakers) may retain + routing information from the restarting speaker while a BGP session with it is being re-established, + reducing route flapping. + + + Subclass of AvdModel. + """ + bgp_maximum_paths: int | None + """ + Maximum Paths for BGP multi-path. + The default value is 4 except for WAN Routers where the default + value is 16. + """ + bgp_mesh_pes: bool + """ + Configure an iBGP full mesh between PEs, either because there is no RR used or other reasons. + Only + supported in combination with MPLS overlay. + + Default value: `False` + """ + bgp_peer_groups: BgpPeerGroups + """ + Leverage an Arista EOS switch to generate the encrypted password using the correct peer group name. + Note that the name of the peer groups use '-' instead of '_' in EOS configuration. + + + Subclass of + AvdModel. + """ + bgp_update_wait_install: bool + """ + Do not advertise reachability to a prefix until that prefix has been installed in hardware. + This + will eliminate any temporary black holes due to a BGP speaker advertising reachability to a prefix + that may not yet be installed into the forwarding plane. + + Default value: `True` + """ + bgp_update_wait_for_convergence: bool + """ + Disables FIB updates and route advertisement when the BGP instance is initiated until the BGP + convergence state is reached. + + Default value: `False` + """ + connected_endpoints_keys: ConnectedEndpointsKeys + """ + Endpoints connecting to the fabric can be grouped by using separate keys. + The keys can be customized + to provide a better better organization or grouping of your data. + `connected_endpoints_keys` should + be defined in the top level group_vars for the fabric. + The default values will be overridden if + defining this key, so it is recommended to copy the defaults and modify them. + + + Subclass of + AvdIndexedList with `ConnectedEndpointsKeysItem` items. Primary key is `key` (`str`). + + Default value: `lambda cls: coerce_type([{"key": "servers", "type": "server", "description": "Server"}, {"key": "firewalls", "type": "firewall", "description": "Firewall"}, {"key": "routers", "type": "router", "description": "Router"}, {"key": "load_balancers", "type": "load_balancer", "description": "Load Balancer"}, {"key": "storage_arrays", "type": "storage_array", "description": "Storage Array"}, {"key": "cpes", "type": "cpe", "description": "CPE"}, {"key": "workstations", "type": "workstation", "description": "Workstation"}, {"key": "access_points", "type": "access_point", "description": "Access Point"}, {"key": "phones", "type": "phone", "description": "Phone"}, {"key": "printers", "type": "printer", "description": "Printer"}, {"key": "cameras", "type": "camera", "description": "Camera"}, {"key": "generic_devices", "type": "generic_device", "description": "Generic Device"}], target_type=cls)` + """ + core_interfaces: CoreInterfaces + """Subclass of AvdModel.""" + custom_structured_configuration_list_merge: Literal["replace", "append", "keep", "prepend", "append_rp", "prepend_rp"] + """ + The List-merge strategy used when merging custom structured configurations. + + This applies to all + vars prefixed by prefixes in `custom_structured_configuration_prefix` + and all data under the various + `structured_config` options. + + The available list merge strategies: + - `replace`: + - Any list will be + replaced with the list defined in custom structured configurations. + - `append`: + - Existing list + items with the same "Primary key"-value will be updated. + - New items will be appended to the + existing list (including duplicates). + - `keep`: + - Only set list if there is no existing list or + existing list is `None`. + - `prepend`: + - Existing list items with the same "Primary key"-value will + be updated. + - New items will be prepended to the existing list (including duplicates). + - + `append_rp`: + - Existing list items with the same "Primary key"-value will be updated. + - New + unique items will be appended to the existing list. + - `prepend_rp`: + - Existing list items with the + same "Primary key"-value will be updated. + - New unique items will be prepended to the existing + list. + + Default value: `"append_rp"` + """ + custom_structured_configuration_prefix: CustomStructuredConfigurationPrefix + """ + Custom EOS Structured Configuration keys can be set on any group or host_var level using the name + of + the corresponding `eos_cli_config_gen` key prefixed with content of + `custom_structured_configuration_prefix`. + + The content of Custom Structured Configuration variables + will be merged with the structured config generated by the eos_designs role. + + The merge is done + recursively, so it is possible to update a sub-key of a variable set by `eos_designs` role already. + The merge follow these recursive merge strategies: + - New keys will be added for all types. + - + Existing keys of type "List" with a "Primary key" set in the schema: + - Strategy can be changed + with `custom_structured_configuration_list_merge`. Default strategy: + - Existing list items with + the same "Primary key"-value will be updated. + - New unique items will be appended to the + existing list + - Other keys of type "List" will have new unique items appended the the existing list. + - Existing keys of type "Dictionary" will recursively merge + - Other existing keys will be replaced. + Subclass of AvdList with `str` items. + + Default value: `lambda cls: coerce_type(["custom_structured_configuration_"], target_type=cls)` + """ + cv_pathfinder_global_sites: CvPathfinderGlobalSites + """ + Define sites that are outside of the CV Pathfinder hierarchy. + This is used to arrange pathfinders in + the CloudVision topology layout. + + Subclass of AvdIndexedList with `CvPathfinderGlobalSitesItem` + items. Primary key is `name` (`str`). + """ + cv_pathfinder_internet_exit_policies: CvPathfinderInternetExitPolicies + """ + PREVIEW: These keys are in preview mode. + + List of internet-exit policies used for the WAN + configuration. + + Subclass of AvdIndexedList with `CvPathfinderInternetExitPoliciesItem` items. + Primary key is `name` (`str`). + """ + cv_pathfinder_regions: CvPathfinderRegions + """ + Define the CV Pathfinder hierarchy. + + Subclass of AvdIndexedList with `CvPathfinderRegionsItem` + items. Primary key is `name` (`str`). + """ + cv_server: str | None + """ + PREVIEW: These keys are in preview mode. + + Hostname or IP address of CloudVision host. Ex. + "www.arista.io" for CVaaS. + For `eos_designs` this variable is only used for the WAN Internet-exit + integration with Zscaler. + The same variable name is also used by the `cv_deploy` role, and will + override the value of `ansible_host` on inventory 'cloudvision' host. + Make sure to set it in a + common group_vars file. + """ + cv_tags_topology_type: Literal["leaf", "spine", "core", "edge"] | None + """ + PREVIEW: This key is currently not supported + Device type that CloudVision should use when generating + the Topology. Defaults to the setting under node_type_keys. + """ + cv_token: str | None + """ + PREVIEW: These keys are in preview mode. + + Service account token as defined on CloudVision. This + value should be using Ansible Vault. + For `eos_designs` this variable is only used for the WAN + Internet-exit integration with Zscaler. + The same variable name is also used by the `cv_deploy` role, + and will override the value of `ansible_password` on inventory 'cloudvision' host. + Make sure to set + it in a common group_vars file. + """ + cv_topology: CvTopology + """ + Generate AVD configurations directly from the given CloudVision topology. + Activate this feature by + setting `use_cv_topology` to `true`. + Requires `default_interfaces` to be set for the relevant + platforms and node types to detect the proper interface roles automatically. + Neighbor hostnames must + match the inventory hostnames of the AVD inventory to be taken into consideration. + + Subclass of + AvdIndexedList with `CvTopologyItem` items. Primary key is `hostname` (`str`). + """ + cvp_ingestauth_key: str | None + """ + On-premise CVP ingest auth key. If set, TerminAttr will be configured with key-based authentication + for on-premise CVP. + If not set, TerminAttr will be configured with certificate based authentication: + - On-premise using token onboarding. Default token path is '/tmp/token'. + - CVaaS using token-secure + onboarding. Default token path is '/tmp/cv-onboarding-token'. + Token must be copied to the device + first. + """ + cvp_instance_ips: CvpInstanceIps + """ + List of IPv4 addresses or DNS names for CloudVision. + For on-premise CloudVision enter all the nodes + of the cluster. + For CloudVision as a Service enter the DNS name of the instance. + `eos_designs` only + supports one CloudVision cluster. + + + Subclass of AvdList with `str` items. + """ + cvp_token_file: str | None + """ + cvp_token_file is the path to the token file on the switch. + If not set the default locations for on- + premise or CVaaS will be used. + See cvp_ingestauth_key for details. + """ + dc_name: str | None + """ + DC Name is used in: + - Fabric Documentation (Optional, falls back to fabric_name) + - SNMP Location: + `snmp_settings.location` (Optional) + - HER Overlay DC scoped flood lists: + `overlay_her_flood_list_scope: dc` (Required) + """ + default_connected_endpoints_description: str + """ + Default description or description template to be used on all ports to connected endpoints. + This can + be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `endpoint_type`: The `type` from + `connected_endpoints_keys` like `server`, `router` etc. + - `endpoint`: The name of the connected + endpoint + - `endpoint_port`: The value from `endpoint_ports` for this switch port if set. + - + `port_channel_id`: The port-channel number for the switch. + + By default the description is templated + from the type, name and port of the endpoint if set. + + Default value: `"{endpoint_type!u}_{endpoint}{endpoint_port?<_}"` + """ + default_connected_endpoints_port_channel_description: str + """ + Default description or description template to be used on all port-channels to connected endpoints. + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `endpoint_type`: The `type` from + `connected_endpoints_keys` like `server`, `router` etc. + - `endpoint`: The name of the connected + endpoint + - `endpoint_port_channel`: The value of `endpoint_port_channel` if set. + - + `port_channel_id`: The port-channel number for the switch. + - `adapter_description`: The adapter's + description if set. + - `adapter_description_or_endpoint`: Helper alias of the adapter_description + or endpoint. + + By default the description is templated from the type, name and port-channel name of + the endpoint if set. + + Default value: `"{endpoint_type!u}_{endpoint}{endpoint_port_channel?<_}"` + """ + default_igmp_snooping_enabled: bool + """ + When set to false, disables IGMP snooping at fabric level and overrides per vlan settings. + + Default value: `True` + """ + default_interface_mtu: int | None + """ + Default interface MTU configured on EOS under "interface defaults". + Can be overridden per platform + under platform settings. + """ + default_interfaces: DefaultInterfaces + """ + Default uplink, downlink, and MLAG interfaces, which will be used if these interfaces are not + defined on a device (either directly or through inheritance). + + + Subclass of AvdList with + `DefaultInterfacesItem` items. + """ + default_mgmt_method: Literal["oob", "inband", "none"] + """ + `default_mgmt_method` controls the default VRF and source interface used for the following + management and monitoring protocols configured with `eos_designs`: + - `ntp_settings` + - + `sflow_settings` + + `oob` means the protocols will be configured with the VRF set by + `mgmt_interface_vrf` and `mgmt_interface` as the source interface. + `inband` means the protocols will + be configured with the VRF set by `inband_mgmt_vrf` and `inband_mgmt_interface` as the source + interface. + `none` means the VRF and or interface must be manually set for each protocol. + This can be + overridden under the settings for each protocol. + + Default value: `"oob"` + """ + default_network_ports_description: str + """ + Default description or description template to be used on all ports defined under `network_ports`. + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `endpoint_type`: Always set to + `network_port`. + - `endpoint`: The value of the `endpoint` key if set. + - `port_channel_id`: The + port-channel number for the switch. + + By default the description is templated from the `endpoint` key + if set. + + Default value: `"{endpoint?}"` + """ + default_network_ports_port_channel_description: str + """ + Default description or description template to be used on all port-channels defined under + `network_ports`. + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `endpoint_type`: Always set to + `network_port`. + - `endpoint`: The value of the `endpoint` key if set. + - `endpoint_port_channel`: + The value of `endpoint_port_channel` if set. + - `port_channel_id`: The port-channel number for the + switch. + - `adapter_description`: The adapter's description if set. + - + `adapter_description_or_endpoint`: Helper alias of the adapter_description or endpoint. + + By default + the description is templated from the `endpoint` key if set. + + Default value: `"{endpoint?}{endpoint_port_channel?<_}"` + """ + default_node_types: DefaultNodeTypes + """ + Uses hostname matches against a regular expression to determine the node type. + + Subclass of + AvdIndexedList with `DefaultNodeTypesItem` items. Primary key is `node_type` (`str`). + """ + default_underlay_p2p_ethernet_description: str + """ + The default description or description template to be used on L3 point-to-point ethernet interfaces. + The interfaces using this are the routed uplinks and `p2p_links` defined under `l3_edge` or + `core_interfaces`. + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `peer`: The name of the peer. + - + `interface`: The local interface name. + - `peer_interface`: The interface on the peer. + - `vrf`: + The name of the VRF if set (Only applicable for `uplink_type: p2p-vrfs`). + + By default the + description is templated from the name and interface of the peer. + + Default value: `"P2P_{peer}_{peer_interface}{vrf?<_VRF_}"` + """ + default_underlay_p2p_port_channel_description: str + """ + The default description or description template to be used on L3 point-to-point port-channel + interfaces. + The port-channels using this are `p2p_links` defined under `l3_edge` or + `core_interfaces`. + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `peer`: The name of the peer. + - + `interface`: The local interface name. + - `peer_interface`: The interface on the peer. + - + `port_channel_id`: The local port-channel ID. + - `peer_port_channel_id`: The ID of the port-channel + on the peer. + + By default the description is templated from the name and interface of the peer. + + Default value: `"P2P_{peer}_{peer_interface}"` + """ + default_vrf_diag_loopback_description: str + """ + The default description or description template to be used on VRF diagnostic loopback interfaces. + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `interface`: The Loopback interface + name. + - `vrf`: The VRF name. + - `tenant`: The tenant name. + + By default the description is + templated from the VRF name. + + Default value: `"DIAG_VRF_{vrf}"` + """ + design: Design + """Subclass of AvdModel.""" + enable_trunk_groups: bool + """ + Enable Trunk Group support across eos_designs. + Warning: Because of the nature of the EOS Trunk Group + feature, enabling this is "all or nothing". + *All* vlans and *all* trunks towards connected endpoints + must be using trunk groups as well. + If trunk groups are not assigned to a trunk, no vlans will be + enabled on that trunk. + See "Details on enable_trunk_groups" below before enabling this feature. + + Default value: `False` + """ + eos_designs_custom_templates: EosDesignsCustomTemplates + """Subclass of AvdList with `EosDesignsCustomTemplatesItem` items.""" + eos_designs_documentation: EosDesignsDocumentation + """ + Control fabric documentation generation. + + + Subclass of AvdModel. + """ + event_handlers: EventHandlers + """ + Gives the ability to monitor and react to Syslog messages. + Event Handlers provide a powerful and + flexible tool that can be used to apply self-healing actions, + customize the system behavior, and + implement workarounds to problems discovered in the field. + """ + evpn_ebgp_gateway_inter_domain: bool | None + evpn_ebgp_gateway_multihop: int + """ + Default of 15, considering a large value to avoid BGP reachability issues in very complex DCI + networks. + Adapt the value for your specific topology. + + Default value: `15` + """ + evpn_ebgp_multihop: int + """ + Default of 3, the recommended value for a 3 stage spine and leaf topology. + Set to a higher value to + allow for very large and complex topologies. + + Default value: `3` + """ + evpn_hostflap_detection: EvpnHostflapDetection + """Subclass of AvdModel.""" + evpn_import_pruning: bool + """ + Enable VPN import pruning (Min. EOS 4.24.2F). + The Route Target extended communities carried by + incoming VPN paths will be examined. + If none of those Route Targets have been configured for import, + the path will be immediately discarded. + + Default value: `False` + """ + evpn_multicast: bool + """ + General Configuration required for EVPN Multicast. "evpn_l2_multicast" or "evpn_l3_multicast" must + also be configured under the Network Services (tenants). + Requires "underlay_multicast: true" and + IGMP snooping enabled globally (default). + For MLAG devices Route Distinguisher must be unique since + this feature will create multi-vtep configuration. + Warning !!! For Trident3 based platforms i.e + 7050X3, 7300X3, 720XP. + The Following default platform setting will be configured on 7050X3 and + 7300X3: "platform trident forwarding-table partition flexible exact-match 16384 l2-shared 98304 + l3-shared 131072" + The Following default platform setting will be configured on 720XP: "flexible + exact-match 16000 l2-shared 18000 l3-shared 22000" + All forwarding agents will be restarted when + this configuration is applied. + You can tune the settings by overriding the default variable: + "platform_settings[platforms].trident_forwarding_table_partition:" + Please contact an Arista + representative for help with determining the appropriate values for your environment. + + Default value: `False` + """ + evpn_overlay_bgp_rtc: bool + """ + Enable Route Target Membership Constraint Address Family on EVPN overlay BGP peerings (Min. EOS + 4.25.1F). + Requires use eBGP as overlay protocol. + + Default value: `False` + """ + evpn_prevent_readvertise_to_server: bool + """ + Configure route-map on eBGP sessions towards route-servers, where prefixes with the peer's ASN in + the AS Path are filtered away. + This is very useful in large-scale networks, where convergence will + be quicker by not returning all updates received + from Route-server-1 to Router-server-2 just for + Route-server-2 to throw them away because of AS Path loop detection. + + Default value: `False` + """ + evpn_short_esi_prefix: str + """ + Configure prefix for "short_esi" values. + + Default value: `"0000:0000:"` + """ + evpn_vlan_aware_bundles: bool + """ + Enable VLAN aware bundles for every EVPN MAC-VRF. + If set to `true` all SVIs in a VRF are configured + in a vlan-aware-bundle using the VRF name as the bundle name. `l2vlans` are bundled in vlan-aware- + bundles using the VLAN name as the bundle name. + + The `evpn_vlan_bundle` option under `svis` and + `l2vlans` takes precedence and overrides this behavior. Per svi/l2vlan `evpn_vlan_bundle` also works + when this setting is disabled which allow mixing vlan-aware-bundles with regular MAC-VRFs. + + Default value: `False` + """ + evpn_vlan_bundles: EvpnVlanBundles + """Subclass of AvdIndexedList with `EvpnVlanBundlesItem` items. Primary key is `name` (`str`).""" + fabric_evpn_encapsulation: Literal["vxlan", "mpls"] | None + """ + Should be set to mpls for evpn-mpls scenario. This overrides the evpn_encapsulation setting under + node_type_keys. + """ + fabric_flow_tracking: FabricFlowTracking + """ + Default enabling of flow-tracking(IPFIX) for various interface types across the fabric. + Flow + Tracking can also be enabled/disabled under each of the specific data models. + For general flow- + tracking settings see `flow_tracking_settings`. + + Subclass of AvdModel. + """ + fabric_ip_addressing: FabricIpAddressing + """Subclass of AvdModel.""" + fabric_name: str + """ + Fabric Name, required to match Ansible Group name covering all devices in the Fabric, **must** be an + inventory group name. + """ + fabric_sflow: FabricSflow + """ + Default enabling of sFlow for various interface types across the fabric. + sFlow can also be + enabled/disabled under each of the specific data models. + For general sFlow settings see + `sflow_settings`. + + Subclass of AvdModel. + """ + flow_tracking_settings: FlowTrackingSettings + """ + Define the flow tracking parameters for this topology. + + Subclass of AvdModel. + """ + generate_cv_tags: GenerateCvTags + """ + PREVIEW: This key is currently not supported + Generate CloudVision Tags based on AVD data. + + Subclass + of AvdModel. + """ + hardware_counters: HardwareCounters + """Subclass of AvdModel.""" + internal_vlan_order: InternalVlanOrder + """ + Internal vlan allocation order and range. + + Subclass of AvdModel. + + Default value: `lambda cls: coerce_type({"allocation": "ascending", "range": {"beginning": 1006, "ending": 1199}}, target_type=cls)` + """ + ipv4_acls: Ipv4Acls + """ + IPv4 extended access-lists supporting substitution on certain fields. + These access-lists can be + referenced under node settings `l3_interfaces`, and will only be configured on devices where they + are in use. + + The substitution is useful when assigning the same access-list on multiple interfaces, + but where certain fields require unique values like the "interface_ip" or "peer_ip". + When using + substitution, the interface name will be appended to the ACL name. + + Subclass of AvdIndexedList with + `Ipv4AclsItem` items. Primary key is `name` (`str`). + """ + ipv4_prefix_list_catalog: Ipv4PrefixListCatalog + """ + IPv4 prefix-list catalog. + + Subclass of AvdIndexedList with `Ipv4PrefixListCatalogItem` items. + Primary key is `name` (`str`). + """ + ipv6_mgmt_destination_networks: Ipv6MgmtDestinationNetworks + """ + List of IPv6 prefixes to configure as static routes towards the OOB IPv6 Management interface + gateway. + Replaces the default route. + + + Subclass of AvdList with `str` items. + """ + ipv6_mgmt_gateway: str | None + """ + OOB Management interface gateway in IPv6 format. + Used as next-hop for default gateway or static + routes defined under 'ipv6_mgmt_destination_networks'. + """ + is_deployed: bool + """ + If the device is already deployed in the fabric. + When set to false, interfaces toward this device + may be shutdown depending on the `shutdown_interfaces_towards_undeployed_peers` setting. + Furthermore + `eos_config_deploy_cvp` will not attempt to move or apply configurations to the device. + + Default value: `True` + """ + isis_advertise_passive_only: bool + """Default value: `False`""" + isis_area_id: str + """Default value: `"49.0001"`""" + isis_default_circuit_type: Literal["level-1-2", "level-1", "level-2"] + """ + These fabric level parameters can be used with core_interfaces running ISIS, and may be overridden + on link profile or link level. + + Default value: `"level-2"` + """ + isis_default_is_type: Literal["level-1-2", "level-1", "level-2"] + """Default value: `"level-2"`""" + isis_default_metric: int + """ + These fabric level parameters can be used with core_interfaces running ISIS, and may be overridden + at link profile or link level. + + Default value: `50` + """ + isis_maximum_paths: int + """ + Number of path to configure in ECMP for ISIS. + + Default value: `4` + """ + isis_system_id_format: Literal["node_id", "underlay_loopback"] + """ + Configures source for the system-id within the ISIS net id. + If this key is set to `node_id`, the + fields `id` and `isis_system_id_prefix` configured under the node attributes are used to generate + the system-id. + If `underlay_loopback` is selected then all node `isis_system_id_prefix` settings + will be ignored and the loopback address will be used to generate the system-id. + + Default value: `"underlay_loopback"` + """ + isis_ti_lfa: IsisTiLfa + """Subclass of AvdModel.""" + l3_edge: L3Edge + """Subclass of AvdModel.""" + l3_interface_profiles: L3InterfaceProfiles + """ + Profiles to inherit common settings for l3_interfaces defined under the node type key. + These + profiles will *not* work for `l3_interfaces` defined under `vrfs`. + + Subclass of AvdIndexedList with + `L3InterfaceProfilesItem` items. Primary key is `profile` (`str`). + """ + local_users: LocalUsers + mac_address_table: MacAddressTable + """ + MAC address-table aging time. + Use to change the EOS default of 300. + + + Subclass of AvdModel. + """ + management_eapi: ManagementEapi + """ + Default is HTTPS management eAPI enabled. + The VRF is set to < mgmt_interface_vrf >. + + + Subclass of + AvdModel. + """ + mgmt_destination_networks: MgmtDestinationNetworks + """ + List of IPv4 prefixes to configure as static routes towards the OOB Management interface gateway. + Replaces the default route. + + Subclass of AvdList with `str` items. + """ + mgmt_gateway: str | None + """ + OOB Management interface gateway in IPv4 format. + Used as next-hop for default gateway or static + routes defined under 'mgmt_destination_networks'. + """ + mgmt_interface: str + """ + OOB Management interface. + + Default value: `"Management1"` + """ + mgmt_interface_description: str + """ + Management interface description. + + Default value: `"OOB_MANAGEMENT"` + """ + mgmt_interface_vrf: str + """ + OOB Management VRF. + + Default value: `"MGMT"` + """ + mgmt_vrf_routing: bool + """ + Configure IP routing for the OOB Management VRF. + + Default value: `False` + """ + mlag_bgp_peer_description: str + """ + Description or description template to be used on the MLAG BGP peers including those in VRFs. + This + can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `mlag_peer`: The name of the MLAG + peer. + - `interface`: The local MLAG L3 VLAN interface. + - `peer_interface`: The MLAG L3 VLAN + interface on the MLAG peer. + - `vrf`: The name of the VRF. Not available for the underlay peering. + The default description is built from the name and interface of the MLAG peer and optionally the + VRF. + + Default value: `"{mlag_peer}_{peer_interface}"` + """ + mlag_bgp_peer_group_description: str + """ + Description or description template to be used on the MLAG BGP peer-group. + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `mlag_peer`: The name of the MLAG peer. + + The default description is the name of the MLAG peers. + + Default value: `"{mlag_peer}"` + """ + mlag_ibgp_peering_vrfs: MlagIbgpPeeringVrfs + """ + On mlag leafs, an SVI interface is defined per vrf, to establish iBGP peering (required when there + are MLAG leafs in topology). + The SVI id will be derived from the base vlan defined: + mlag_ibgp_peering_vrfs.base_vlan + (vrf_id or vrf_vni) - 1. + Depending on the values of vrf_id / + vrf_vni it may be required to adjust the base_vlan to avoid overlaps or invalid vlan ids. + The SVI ip + address derived from mlag_l3_peer_ipv4_pool is re-used across all iBGP peerings. + + + Subclass of + AvdModel. + """ + mlag_member_description: str + """ + Description or description template to be used on MLAG peer-link ethernet interfaces. + This can be a + template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `mlag_peer`: The name of the MLAG + peer. + - `interface`: The local MLAG port-channel interface. + - `peer_interface`: The port-channel + interface on the MLAG peer. + - `mlag_port_channel_id`: The local MLAG port-channel ID. + - + `mlag_peer_port_channel_id`: The port-channel ID on the MLAG peer. + + By default the description is + templated from the name and interface of the MLAG peer. + + Default value: `"MLAG_{mlag_peer}_{peer_interface}"` + """ + mlag_on_orphan_port_channel_downlink: bool + """ + If `true` an MLAG ID will always be configured on a Port-Channel downlink even if the downlink is + only on one node in the MLAG pair. + If `false` (default) an MLAG ID will only be configured on Port- + Channel downlinks dual-homed to two MLAG switches. + + Default value: `False` + """ + mlag_peer_l3_svi_description: str + """ + Description or description template to be used on MLAG L3 peering SVI (Interface Vlan4093 by + default). + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `mlag_peer`: The name of the MLAG + peer. + - `interface`: The MLAG L3 peering SVI name. + - `mlag_peer_l3_vlan`: The MLAG L3 peering + VLAN ID. + + Default value: `"MLAG_L3"` + """ + mlag_peer_l3_vlan_name: str + """ + Name or name template to be used on MLAG L3 VLAN (VLAN 4093 by default). + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `mlag_peer`: The name of the MLAG peer. + - `mlag_peer_l3_vlan`: The MLAG L3 peering VLAN ID. + + Default value: `"MLAG_L3"` + """ + mlag_peer_l3_vrf_svi_description: str + """ + Description or description template to be used on MLAG L3 peering SVI for VRFs. + This can be a + template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `mlag_peer`: The name of the MLAG + peer. + - `interface`: The MLAG L3 VRF peering SVI name. + - `vlan`: The MLAG L3 VRF peering VLAN + ID. + - `vrf`: The VRF name. + + Default value: `"MLAG_L3_VRF_{vrf}"` + """ + mlag_peer_l3_vrf_vlan_name: str + """ + Name or name template to be used on MLAG L3 peering VLAN for VRFs. + This can be a template using the + AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom- + descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - + `mlag_peer`: The name of the MLAG peer. + - `vlan`: The MLAG L3 VRF peering VLAN ID. + - `vrf`: The + VRF name. + + Default value: `"MLAG_L3_VRF_{vrf}"` + """ + mlag_peer_svi_description: str + """ + Description or description template to be used on MLAG peering SVI (Interface Vlan4094 by default). + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `mlag_peer`: The name of the MLAG + peer. + - `interface`: The MLAG peering SVI name. + - `mlag_peer_vlan`: The MLAG peering VLAN ID. + + Default value: `"MLAG"` + """ + mlag_peer_vlan_name: str + """ + Name or name template to be used on MLAG peering VLAN (VLAN 4094 by default). + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `mlag_peer`: The name of the MLAG peer. + - `mlag_peer_vlan`: The MLAG peering VLAN ID. + + Default value: `"MLAG"` + """ + mlag_port_channel_description: str + """ + Description or description template to be used on MLAG peer-link port-channel interfaces. + This can + be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `mlag_peer`: The name of the MLAG + peer. + - `interface`: The local MLAG port-channel interface. + - `peer_interface`: The port-channel + interface on the MLAG peer. + - `mlag_port_channel_id`: The local MLAG port-channel ID. + - + `mlag_peer_port_channel_id`: The port-channel ID on the MLAG peer. + + By default the description is + templated from the name and port-channel interface of the MLAG peer. + + Default value: `"MLAG_{mlag_peer}_{peer_interface}"` + """ + name_servers: NameServers + """ + List of DNS servers. The VRF is set to < mgmt_interface_vrf >. + + Subclass of AvdList with `str` + items. + """ + network_ports: NetworkPorts + """Subclass of AvdList with `NetworkPortsItem` items.""" + network_services_keys: NetworkServicesKeys + """ + Network Services can be grouped by using separate keys. + The keys can be customized to provide a + better better organization or grouping of your data. + `network_services_keys` should be defined in + the top level group_vars for the fabric. + The default values will be overridden if defining this key, + so it is recommended to copy the defaults and modify them. + + + Subclass of AvdIndexedList with + `NetworkServicesKeysItem` items. Primary key is `name` (`str`). + + Default value: `lambda cls: coerce_type([{"name": "tenants"}], target_type=cls)` + """ + custom_node_type_keys: CustomNodeTypeKeys + """ + Define Custom Node Type Keys, to specify the properties of each node type in the fabric. + This allows + for complete customization of the fabric layout and functionality. + `custom_node_type_keys` should be + defined in top level group_var for the fabric. + These values will be combined with the defaults; + custom node type keys named the same as a + default node_type_key will replace the default. + + Subclass + of AvdIndexedList with `CustomNodeTypeKeysItem` items. Primary key is `key` (`str`). + """ + node_type_keys: NodeTypeKeys + """ + Define Node Type Keys, to specify the properties of each node type in the fabric. + This allows for + complete customization of the fabric layout and functionality. + `node_type_keys` should be defined in + top level group_var for the fabric. + + The default values will be overridden if this key is defined. + If you need to change all the existing `node_type_keys`, it is recommended to copy the defaults and + modify them. + If you need to add custom `node_type_keys`, create them under `custom_node_type_keys` - + if named identically to default `node_type_keys` entries, + custom entries will replace the equivalent + default entry. + + Subclass of AvdIndexedList with `NodeTypeKeysItem` items. Primary key is `key` + (`str`). + """ + ntp_settings: NtpSettings + """ + NTP settings + + Subclass of AvdModel. + """ + only_local_vlan_trunk_groups: bool + """ + A vlan can have many trunk_groups assigned. + To avoid unneeded configuration changes on all leaf + switches when a new trunk group is added, + this feature will only configure the vlan trunk groups + matched with local connected_endpoints. + See "Details on only_local_vlan_trunk_groups" below. + Requires "enable_trunk_groups: true". + + Default value: `False` + """ + overlay_bgp_peer_description: str + """ + Description or description template to be used on the overlay BGP peers. + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `peer`: The name of the BGP peer. + - `peer_interface`: The interface on the BGP peer if + available. + + The default description is built from the name and interface of the BGP peer. + + Default value: `"{peer}{peer_interface?<_}"` + """ + overlay_cvx_servers: OverlayCvxServers + """ + List of CVX vxlan overlay controllers. + Required if overlay_routing_protocol == CVX. + CVX servers + (VMs) are peering using their management interface, so mgmt_ip must be set for all CVX servers. + Subclass of AvdList with `str` items. + """ + overlay_her_flood_list_per_vni: bool + """ + When using Head-End Replication, configure flood-lists per VNI. + By default HER will be configured + with a common flood-list containing all VTEPs. + This behavior can be changed to per-VNI flood-lists + by setting `overlay_her_flood_list_per_vni: true`. + This will make `eos_designs` consider configured + VLANs per VTEP, and only include the relevant VTEPs to each VNI's flood-list. + + Default value: `False` + """ + overlay_her_flood_list_scope: Literal["fabric", "dc"] + """ + When using Head-End Replication, set the scope of flood-lists to Fabric or DC. + By default all VTEPs + in the Fabric (part of the inventory group referenced by "fabric_name") are added to the flood- + lists. + This can be changed to all VTEPs in the DC (sharing the same "dc_name" value). + This is useful + if Border Leaf switches are dividing the VXLAN overlay into separate domains. + + Default value: `"fabric"` + """ + overlay_loopback_description: str | None + """Customize the description on overlay interface Loopback0.""" + overlay_mlag_rfc5549: bool + """ + IPv6 Unnumbered for MLAG iBGP connections. + Requires "underlay_rfc5549: true". + + Default value: `False` + """ + overlay_rd_type: OverlayRdType + """ + Configuration options for the Administrator subfield (first part of RD) and the Assigned Number + subfield (second part of RD). + + By default Route Distinguishers (RD) are set to: + - + `:` for VLANs and VLAN- + Aware Bundles with L2 vlans. + - `:` for + VLAN-Aware Bundles with SVIs. + - `:` for VLAN- + Aware Bundles defined under 'evpn_vlan_bundles'. + - `:` for VRFs. + + Note: + RD + is a 48-bit value which is split into <16-bit>:<32-bit> or <32-bit>:<16-bit>. + When using loopback or + 32-bit ASN/number the assigned number can only be a 16-bit number. This may be a problem with large + VNIs. + For 16-bit ASN/number the assigned number can be a 32-bit number. + + + Subclass of AvdModel. + """ + overlay_routing_protocol: Literal["ebgp", "ibgp", "cvx", "her", "none"] | None + """ + - The following overlay routing protocols are supported: + - ebgp: Configures fabric with eBGP, + default for l3ls-evpn design. + - ibgp: Configured fabric with iBGP, only supported with OSPF or + ISIS variants in underlay, default for mpls design. + - cvx: Configures fabric to leverage + CloudVision eXchange as the overlay controller. + - her: Configures fabric with Head-End + Replication, configures static VXLAN flood-lists instead of using a dynamic overlay protocol. + - + none: No overlay configuration will be generated, default for l2ls design. + + If not set, the + default_overlay_routing_protocol defined under the node_type_keys will be used (default is "ebgp"). + """ + overlay_routing_protocol_address_family: Literal["ipv4", "ipv6"] + """ + When set to `ipv6`, enable overlay EVPN peering with IPv6 addresses. + This feature depends on + underlay_ipv6 variable. As of today, only RFC5549 is capable to transport IPv6 in the underlay. + + Default value: `"ipv4"` + """ + overlay_rt_type: OverlayRtType + """ + Configuration options for the Administrator subfield (first part of RT) and the Assigned Number + subfield (second part of RT). + + By default Route Targets (RT) are set to: + - `<(mac_vrf_id_base or + mac_vrf_vni_base) + vlan_id>:<(mac_vrf_id_base or mac_vrf_vni_base) + vlan_id>` for VLANs and VLAN- + Aware Bundles with L2 vlans. + - `:` for VLAN-Aware Bundles with SVIs. + - + `:` for VLAN-Aware Bundles + defined under 'evpn_vlan_bundles'. + - `:` for VRFs. + + Notes: + RT is a 48-bit value + which is split into <16-bit>:<32-bit> or <32-bit>:<16-bit>. + When using 32-bit ASN/number the VNI can + only be a 16-bit number. Alternatively use vlan_id/vrf_id as assigned number. + For 16-bit ASN/number + the assigned number can be a 32-bit number. + + + Subclass of AvdModel. + """ + p2p_uplinks_mtu: int + """ + Point to Point Links MTU. + Precedence: .uplink_mtu -> platform_settings.p2p_uplinks_mtu -> + p2p_uplinks_mtu -> 9214 + + Default value: `9214` + """ + p2p_uplinks_qos_profile: str | None + """QOS Profile assigned on all infrastructure links.""" + custom_platform_settings: CustomPlatformSettings + """ + Custom Platform settings to override the default `platform_settings`. This list will be prepended to + the list of `platform_settings`. The first entry containing `platforms` matching the `platform` node + setting will be chosen. If no matches are found, the first entry containing a platform `default` + will be chosen. + + Subclass of AvdList with `CustomPlatformSettingsItem` items. + """ + platform_settings: PlatformSettings + """ + Platform settings. The first entry containing `platforms` matching the `platform` node setting will + be chosen. If no matches are found, the first entry containing a platform `default` will be chosen. + The default values will be overridden if `platform_settings` is defined. If you need to replace all + the default platforms, it is recommended to copy the defaults and modify them. If you need to add + custom platforms, create them under `custom_platform_settings`. Entries under + `custom_platform_settings` will be matched before the equivalent entries from `platform_settings`. + Subclass of AvdList with `PlatformSettingsItem` items. + + Default value: `lambda cls: coerce_type([{"platforms": ["default"], "feature_support": {"queue_monitor_length_notify": False}, "reload_delay": {"mlag": 300, "non_mlag": 330}}, {"platforms": ["7050X3"], "feature_support": {"queue_monitor_length_notify": False}, "reload_delay": {"mlag": 300, "non_mlag": 330}, "trident_forwarding_table_partition": "flexible exact-match 16384 l2-shared 98304 l3-shared 131072"}, {"platforms": ["720XP"], "feature_support": {"poe": True, "queue_monitor_length_notify": False}, "reload_delay": {"mlag": 300, "non_mlag": 330}, "trident_forwarding_table_partition": "flexible exact-match 16000 l2-shared 18000 l3-shared 22000"}, {"platforms": ["750", "755", "758"], "management_interface": "Management0", "feature_support": {"poe": True, "queue_monitor_length_notify": False}, "reload_delay": {"mlag": 300, "non_mlag": 330}}, {"platforms": ["720DP", "722XP", "710P"], "feature_support": {"poe": True, "queue_monitor_length_notify": False}, "reload_delay": {"mlag": 300, "non_mlag": 330}}, {"platforms": ["7010TX"], "feature_support": {"queue_monitor_length_notify": False, "per_interface_mtu": False}, "reload_delay": {"mlag": 300, "non_mlag": 330}}, {"platforms": ["7280R", "7280R2", "7020R"], "lag_hardware_only": True, "reload_delay": {"mlag": 900, "non_mlag": 1020}, "tcam_profile": "vxlan-routing"}, {"platforms": ["7280R3"], "reload_delay": {"mlag": 900, "non_mlag": 1020}, "tcam_profile": "vxlan-routing"}, {"platforms": ["7500R", "7500R2"], "lag_hardware_only": True, "management_interface": "Management0", "reload_delay": {"mlag": 900, "non_mlag": 1020}, "tcam_profile": "vxlan-routing"}, {"platforms": ["7500R3", "7800R3"], "management_interface": "Management0", "reload_delay": {"mlag": 900, "non_mlag": 1020}, "tcam_profile": "vxlan-routing"}, {"platforms": ["7358X4"], "management_interface": "Management1/1", "reload_delay": {"mlag": 300, "non_mlag": 330}, "feature_support": {"queue_monitor_length_notify": False, "interface_storm_control": True, "bgp_update_wait_for_convergence": True, "bgp_update_wait_install": False}}, {"platforms": ["7368X4"], "management_interface": "Management0", "reload_delay": {"mlag": 300, "non_mlag": 330}}, {"platforms": ["7300X3"], "management_interface": "Management0", "reload_delay": {"mlag": 1200, "non_mlag": 1320}, "trident_forwarding_table_partition": "flexible exact-match 16384 l2-shared 98304 l3-shared 131072"}, {"platforms": ["VEOS", "VEOS-LAB", "vEOS", "vEOS-lab"], "feature_support": {"bgp_update_wait_for_convergence": False, "bgp_update_wait_install": False, "interface_storm_control": False, "queue_monitor_length_notify": False}, "reload_delay": {"mlag": 300, "non_mlag": 330}}, {"platforms": ["CEOS", "cEOS", "ceos", "cEOSLab"], "feature_support": {"bgp_update_wait_for_convergence": False, "bgp_update_wait_install": False, "interface_storm_control": False, "queue_monitor_length_notify": False}, "management_interface": "Management0", "reload_delay": {"mlag": 300, "non_mlag": 330}}, {"platforms": ["AWE-5310", "AWE-5510", "AWE-7250R", "AWE-7230R"], "feature_support": {"bgp_update_wait_for_convergence": True, "bgp_update_wait_install": False, "interface_storm_control": False, "queue_monitor_length_notify": False}, "management_interface": "Management1/1", "p2p_uplinks_mtu": 9194}, {"platforms": ["AWE-7220R"], "feature_support": {"bgp_update_wait_for_convergence": True, "bgp_update_wait_install": False, "interface_storm_control": False, "queue_monitor_length_notify": False, "poe": True}, "management_interface": "Management1", "p2p_uplinks_mtu": 9194}], target_type=cls)` + """ + platform_speed_groups: PlatformSpeedGroups + """ + Set Hardware Speed Groups per Platform. + + Subclass of AvdIndexedList with `PlatformSpeedGroupsItem` + items. Primary key is `platform` (`str`). + """ + pod_name: str | None + """ + POD Name is used in: + - Fabric Documentation (Optional, falls back to dc_name and then to + fabric_name) + - SNMP Location: `snmp_settings.location` (Optional) + - VRF Loopbacks: + `vtep_diagnostic.loopback_ip_pools.pod` (Required) + + Recommended to be common between Spines and + Leafs within a POD (One l3ls topology). + """ + port_profiles: PortProfiles + """ + Optional profiles to share common settings for connected_endpoints and/or network_ports. + Keys are + the same used under endpoints adapters. Keys defined under endpoints adapters take precedence. + Subclass of AvdIndexedList with `PortProfilesItem` items. Primary key is `profile` (`str`). + """ + ptp_profiles: PtpProfiles + """ + Subclass of AvdIndexedList with `PtpProfilesItem` items. Primary key is `profile` (`str`). + + Default value: `lambda cls: coerce_type([{"profile": "aes67-r16-2016", "announce": {"interval": 0, "timeout": 3}, "delay_req": -3, "sync_message": {"interval": -3}, "transport": "ipv4"}, {"profile": "smpte2059-2", "announce": {"interval": -2, "timeout": 3}, "delay_req": -4, "sync_message": {"interval": -4}, "transport": "ipv4"}, {"profile": "aes67", "announce": {"interval": 2, "timeout": 3}, "delay_req": 0, "sync_message": {"interval": 0}, "transport": "ipv4"}], target_type=cls)` + """ + ptp_settings: PtpSettings + """ + Common PTP settings. + + Subclass of AvdModel. + """ + queue_monitor_length: QueueMonitorLength + """Subclass of AvdModel.""" + redundancy: Redundancy + """ + Redundancy for chassis platforms with dual supervisors | Optional. + + Subclass of AvdModel. + """ + router_id_loopback_description: str + """ + Customize the description on Router ID interface Loopback0. + + Default value: `"ROUTER_ID"` + """ + serial_number: str | None + """ + Serial Number of the device. + Used for documentation purpose in the fabric documentation as can also + be used by the 'eos_config_deploy_cvp' role. + "serial_number" can also be set directly under node + type settings. + If both are set, the value under node type settings takes precedence. + """ + sflow_settings: SflowSettings + """ + sFlow settings. + The sFlow process will only be configured if any interface is enabled for sFlow. + For + default enabling of sFlow for various interface types across the fabric see `fabric_sflow`. + Subclass of AvdModel. + """ + shutdown_bgp_towards_undeployed_peers: bool + """ + When a device is set undeployed using `is_deployed: false` and + `shutdown_bgp_towards_undeployed_peers` key is set to true, the BGP neighborship is shutdown on the + peer. + + Default value: `True` + """ + shutdown_interfaces_towards_undeployed_peers: bool + """ + - It is possible to provision configurations for a complete topology but flag devices as undeployed + using the host level variable `is_deployed: false`. + + ```yaml + # Use at the host level + is_deployed: < + true or false or default -> true > + ``` + + - By default, this will have no impact within the + `eos_designs` role. Configs will still be generated by the `eos_cli_config_gen` role and will still + be pushed by the `eos_config_deploy_eapi` directly to devices if used. + - However, if the + `eos_config_deploy_cvp` role is used to push configurations, CloudVision will ignore the devices + flagged as `is_deployed: false` and not attempt to configure them. + - If the device is not present + in the network due to CloudVision not configuring the device, `eos_validate_state` role will fail + tests on peers of the undeployed device trying to verify that interfaces are up. + - To overcome this + and shutdown interfaces towards undeployed peers, the variable + `shutdown_interfaces_towards_undeployed_peers` can be used, satisfying the `eos_validate_state` role + interface tests. + - Again, this is only an issue if `eos_config_deploy_cvp` is used and the devices + are not present in the network. + + Default value: `True` + """ + snmp_settings: SnmpSettings + """ + SNMP settings. + For SNMP local-interfaces see "source_interfaces.snmp". + Configuration of remote SNMP + engine IDs are currently only possible using `structured_config`. + + Subclass of AvdModel. + """ + source_interfaces: SourceInterfaces + """ + Configure source-interfaces based on the management interfaces set for other `eos_designs` data + models. + By default, no source-interfaces will be configured. They can still be configured manually + using `eos_cli_config_gen` and custom structured configuration. + EOS supports a single source- + interface per VRF, so an error will be raised in case of conflicts. + Errors will also be raised if an + interface is not found for a device. + + Subclass of AvdModel. + """ + svi_profiles: SviProfiles + """ + Profiles to share common settings for SVIs under `.[].vrfs.svis`. + Keys are the + same used under SVIs. Keys defined under SVIs take precedence. + Note: structured configuration is not + merged recursively and will be taken directly from the most specific level in the following order: + 1. svi.nodes[inventory_hostname].structured_config + 2. + svi_profile.nodes[inventory_hostname].structured_config + 3. + svi_parent_profile.nodes[inventory_hostname].structured_config + 4. svi.structured_config + 5. + svi_profile.structured_config + 6. svi_parent_profile.structured_config + + + Subclass of AvdIndexedList + with `SviProfilesItem` items. Primary key is `profile` (`str`). + """ + system_mac_address: str | None + """ + Set to the same MAC address as available in "show version" on the device. + "system_mac_address" can + also be set under node type settings. + If both are set, the value under node type settings takes + precedence. + """ + terminattr_disable_aaa: bool + """Default value: `False`""" + terminattr_ingestexclude: str + """Default value: `"/Sysdb/cell/1/agent,/Sysdb/cell/2/agent"`""" + terminattr_ingestgrpcurl_port: int + """ + Port number used for Terminattr connection to an on-premise CloudVision cluster. + The port number is + always 443 when using CloudVision as a Service, so this value is ignored. + + Default value: `9910` + """ + terminattr_smashexcludes: str + """Default value: `"ale,flexCounter,hardware,kni,pulse,strata"`""" + timezone: str | None + """Clock timezone like "CET" or "US/Pacific".""" + trunk_groups: TrunkGroups + """Subclass of AvdModel.""" + type: str | None + """ + The `type:` variable needs to be defined for each device in the fabric. + This is leveraged to load + the appropriate template to generate the configuration. + """ + underlay_filter_peer_as: bool + """ + Configure route-map on eBGP sessions towards underlay peers, where prefixes with the peer's ASN in + the AS Path are filtered away. + This is very useful in very large scale networks not using EVPN + overlays, where convergence will be quicker by not having to return + all updates received from + Spine-1 to Spine-2 just for Spine-2 to throw them away because of AS Path loop detection. + Note that + this setting cannot be used while there are EVPN services present in the default VRF. + + Default value: `False` + """ + underlay_filter_redistribute_connected: bool + """ + Filter redistribution of connected into the underlay routing protocol. + Only applicable when + overlay_routing_protocol != 'none' and underlay_routing_protocol == BGP. + Creates a route-map and + prefix-list assigned to redistribute connected permitting only loopbacks and inband management + subnets. + + Default value: `True` + """ + underlay_ipv6: bool + """ + This feature allows IPv6 underlay routing protocol with RFC5549 addresses to be used along with IPv4 + advertisements as VXLAN tunnel endpoints. + Requires "underlay_rfc5549: true" and "loopback_ipv6_pool" + under the node type settings. + + Default value: `False` + """ + underlay_isis_authentication_key: str | None + """Type-7 encrypted password.""" + underlay_isis_authentication_mode: Literal["md5", "text"] | None + """Underlay ISIS authentication mode.""" + underlay_isis_bfd: bool + """ + Enable BFD for ISIS on all underlay links. + + Default value: `False` + """ + underlay_isis_instance_name: str | None + """Default -> "EVPN_UNDERLAY" for l3ls, "CORE" for mpls.""" + underlay_l2_ethernet_description: str + """ + The description or description template to be used on L2 ethernet interfaces. + The interfaces using + this are the member interfaces of port-channel uplinks. + This can be a template using the AVD string + formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions- + names.html#avd-string-formatter-syntax. + The available template fields are: + - `peer`: The name of + the peer. + - `interface`: The local interface name. + - `peer_interface`: The interface on the + peer. + + By default the description is templated from the hostname and interface of the peer. + + Default value: `"L2_{peer}_{peer_interface}"` + """ + underlay_l2_port_channel_description: str + """ + The description or description template to be used on L2 port-channel interfaces. + The interfaces + using this are port-channel uplinks. + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `peer`: The name of the peer. + - + `interface`: The local interface name. + - `peer_interface`: The interface on the peer. + - + `port_channel_id`: The local port-channel ID. + - `peer_port_channel_id`: The ID of the port-channel + on the peer. + - `peer_node_group`: The node group of the peer if the peer is an MLAG member or + running EVPN A/A. + - `peer_node_group_or_peer`: Helper alias of the peer_node_group or peer. + - + `peer_node_group_or_uppercase_peer`: Helper alias of the peer_node_group or peer hostname in + uppercase. + + By default the description is templated from the peer's node group (for MLAG or EVPN + A/A) or hostname and port-channel interface of the peer. + + Default value: `"L2_{peer_node_group_or_peer}_{peer_interface}"` + """ + underlay_multicast: bool + """ + Enable Multicast in the underlay on all p2p uplink interfaces and mlag l3 peer interface. + Specifically PIM Sparse-Mode will be configured on all routed underlay interfaces. + No other + configuration is added, so the underlay will only support Source-Specific Multicast (SSM). + The + configuration is intended to be used as multicast underlay for EVPN OISM overlay. + + Default value: `False` + """ + underlay_multicast_anycast_rp: UnderlayMulticastAnycastRp + """ + If multiple nodes are configured under 'underlay_multicast_rps.[].nodes' for the same RP address, + they will be configured + with one of the following methods: + - Anycast RP using PIM (RFC4610). + - + Anycast RP using MSDP (RFC4611). + + NOTE: When using MSDP, all nodes across all MSDP enabled RPs will + be added to a single MSDP mesh group named "ANYCAST-RP". + + + Subclass of AvdModel. + """ + underlay_multicast_rps: UnderlayMulticastRps + """ + List of PIM Sparse-Mode Rendevouz Points configured for underlay multicast on all devices. + The + device(s) listed under 'nodes', will be configured as the Rendevouz point router(s). + If multiple + nodes are configured under 'nodes' for the same RP address, they will be configured + according to the + 'underlay_multicast_anycast_rp.mode' setting. + + Requires 'underlay_multicast: true'. + + + Subclass of + AvdIndexedList with `UnderlayMulticastRpsItem` items. Primary key is `rp` (`str`). + """ + underlay_ospf_area: str + """Default value: `"0.0.0.0"`""" + underlay_ospf_authentication: UnderlayOspfAuthentication + """Subclass of AvdModel.""" + underlay_ospf_bfd_enable: bool + """Default value: `False`""" + underlay_ospf_max_lsa: int + """Default value: `12000`""" + underlay_ospf_process_id: int + """Default value: `100`""" + underlay_rfc5549: bool + """ + Point to Point Underlay with RFC 5549(eBGP), i.e. IPv6 Unnumbered. + Requires + "underlay_routing_protocol: ebgp". + + Default value: `False` + """ + underlay_routing_protocol: Literal["ebgp", "ospf", "ospf-ldp", "isis", "isis-sr", "isis-ldp", "isis-sr-ldp", "none"] | None + """ + - The following underlay routing protocols are supported: + - EBGP (default for l3ls-evpn) + - OSPF. + - OSPF-LDP*. + - ISIS. + - ISIS-SR*. + - ISIS-LDP*. + - ISIS-SR-LDP*. + - No underlay routing + protocol (none) + - The variables should be applied to all devices in the fabric. + *Only supported with + core_interfaces data model. + """ + uplink_ptp: UplinkPtp + """ + Enable PTP on all infrastructure links. + + Subclass of AvdModel. + """ + use_cv_topology: bool | None + """ + Generate AVD configurations directly from a given CloudVision topology. + See `cv_topology` for + details. + """ + use_router_general_for_router_id: bool + """ + Use `router general` to set router ID for all routing protocols and VRFs. + + Default value: `False` + """ + vtep_loopback_description: str + """ + Customize the description on the VTEP interface, typically Loopback1. + + Default value: `"VXLAN_TUNNEL_SOURCE"` + """ + vtep_vvtep_ip: str | None + """ + IP Address used as Virtual VTEP. Will be configured as secondary IP on Loopback1. + This is only + needed for centralized routing designs. + """ + wan_carriers: WanCarriers + """ + List of carriers used for the WAN configuration and their mapping to path-groups. + + Subclass of + AvdIndexedList with `WanCarriersItem` items. Primary key is `name` (`str`). + """ + wan_encapsulation: Literal["path-selection", "vxlan"] + """ + Select the encapsulation to use for EVPN peerings for WAN BGP peers. + + Default value: `"path-selection"` + """ + wan_ha: WanHa + """ + PREVIEW: The `wan_ha` key is currently not supported. + + Subclass of AvdModel. + """ + wan_ipsec_profiles: WanIpsecProfiles + """ + Define IPsec profiles parameters for WAN configuration. + + Subclass of AvdModel. + """ + wan_mode: Literal["autovpn", "cv-pathfinder"] + """ + Select if the WAN should be run using CV Pathfinder or AutoVPN only. + + Default value: `"cv-pathfinder"` + """ + wan_path_groups: WanPathGroups + """ + List of path-groups used for the WAN configuration. + + Subclass of AvdIndexedList with + `WanPathGroupsItem` items. Primary key is `name` (`str`). + """ + wan_route_servers: WanRouteServers + """ + List of the AutoVPN RRs when using `wan_mode: autovpn`, or the Pathfinders + when using `wan_mode: cv- + pathfinder`, to which the device should connect to. + This is also used to establish iBGP sessions + between WAN route servers. + + When the route server is part of the same inventory as the WAN routers, + only the name is required. + + Subclass of AvdIndexedList with `WanRouteServersItem` items. Primary key + is `hostname` (`str`). + """ + wan_stun_dtls_disable: bool + """ + WAN STUN connections are authenticated and secured with DTLS by default. + For CV Pathfinder + deployments CloudVision will automatically deploy certificates on the devices. + In case of AutoVPN + the certificates must be deployed manually to all devices. + + For LAB environments this can be + disabled, if there are no certificates available. + This should NOT be disabled for a WAN network + connected to the internet, since it will leave the STUN service exposed with no authentication. + + Default value: `False` + """ + wan_stun_dtls_profile_name: str + """ + Name of the SSL profile used for DTLS on WAN STUN connections. + When using automatic ceritficate + deployment via CloudVision this name must be the same on all WAN routers. + + Default value: `"STUN-DTLS"` + """ + wan_virtual_topologies: WanVirtualTopologies + """ + Configure Virtual Topologies for CV Pathfinder and AutoVPN. + Auto create a control plane + profile/policy/application and enforce it being first in the default VRF. + + Subclass of AvdModel. + """ + zscaler_endpoints: ZscalerEndpoints + """ + PREVIEW: These keys are in preview mode. + + Special data model used for testing the WAN internet-exit + integration with Zscaler. + The model is supposed to be autofilled per-device by `eos_designs`. + Manually setting this model will take precedence and prevent `eos_designs` from trying to contact + CloudVision. + This can be useful for offline testing or if CloudVision is not available or not + configured for Zscaler integration. + + Subclass of AvdModel. + """ + _custom_data: dict[str, Any] + _custom_structured_configurations: _CustomStructuredConfigurations + _dynamic_keys: _DynamicKeys + """Dynamic keys""" + + if TYPE_CHECKING: + + def __init__( + self, + *, + application_classification: ApplicationClassification | UndefinedType = Undefined, + avd_data_validation_mode: Literal["error", "warning"] | UndefinedType = Undefined, + avd_eos_designs_debug: bool | UndefinedType = Undefined, + avd_eos_designs_structured_config: bool | UndefinedType = Undefined, + avd_eos_designs_unset_facts: bool | UndefinedType = Undefined, + bfd_multihop: BfdMultihop | UndefinedType = Undefined, + bgp_as: str | None | UndefinedType = Undefined, + bgp_default_ipv4_unicast: bool | UndefinedType = Undefined, + bgp_distance: BgpDistance | UndefinedType = Undefined, + bgp_ecmp: int | None | UndefinedType = Undefined, + bgp_graceful_restart: BgpGracefulRestart | UndefinedType = Undefined, + bgp_maximum_paths: int | None | UndefinedType = Undefined, + bgp_mesh_pes: bool | UndefinedType = Undefined, + bgp_peer_groups: BgpPeerGroups | UndefinedType = Undefined, + bgp_update_wait_install: bool | UndefinedType = Undefined, + bgp_update_wait_for_convergence: bool | UndefinedType = Undefined, + connected_endpoints_keys: ConnectedEndpointsKeys | UndefinedType = Undefined, + core_interfaces: CoreInterfaces | UndefinedType = Undefined, + custom_structured_configuration_list_merge: Literal["replace", "append", "keep", "prepend", "append_rp", "prepend_rp"] | UndefinedType = Undefined, + custom_structured_configuration_prefix: CustomStructuredConfigurationPrefix | UndefinedType = Undefined, + cv_pathfinder_global_sites: CvPathfinderGlobalSites | UndefinedType = Undefined, + cv_pathfinder_internet_exit_policies: CvPathfinderInternetExitPolicies | UndefinedType = Undefined, + cv_pathfinder_regions: CvPathfinderRegions | UndefinedType = Undefined, + cv_server: str | None | UndefinedType = Undefined, + cv_tags_topology_type: Literal["leaf", "spine", "core", "edge"] | None | UndefinedType = Undefined, + cv_token: str | None | UndefinedType = Undefined, + cv_topology: CvTopology | UndefinedType = Undefined, + cvp_ingestauth_key: str | None | UndefinedType = Undefined, + cvp_instance_ips: CvpInstanceIps | UndefinedType = Undefined, + cvp_token_file: str | None | UndefinedType = Undefined, + dc_name: str | None | UndefinedType = Undefined, + default_connected_endpoints_description: str | UndefinedType = Undefined, + default_connected_endpoints_port_channel_description: str | UndefinedType = Undefined, + default_igmp_snooping_enabled: bool | UndefinedType = Undefined, + default_interface_mtu: int | None | UndefinedType = Undefined, + default_interfaces: DefaultInterfaces | UndefinedType = Undefined, + default_mgmt_method: Literal["oob", "inband", "none"] | UndefinedType = Undefined, + default_network_ports_description: str | UndefinedType = Undefined, + default_network_ports_port_channel_description: str | UndefinedType = Undefined, + default_node_types: DefaultNodeTypes | UndefinedType = Undefined, + default_underlay_p2p_ethernet_description: str | UndefinedType = Undefined, + default_underlay_p2p_port_channel_description: str | UndefinedType = Undefined, + default_vrf_diag_loopback_description: str | UndefinedType = Undefined, + design: Design | UndefinedType = Undefined, + enable_trunk_groups: bool | UndefinedType = Undefined, + eos_designs_custom_templates: EosDesignsCustomTemplates | UndefinedType = Undefined, + eos_designs_documentation: EosDesignsDocumentation | UndefinedType = Undefined, + event_handlers: EventHandlers | UndefinedType = Undefined, + evpn_ebgp_gateway_inter_domain: bool | None | UndefinedType = Undefined, + evpn_ebgp_gateway_multihop: int | UndefinedType = Undefined, + evpn_ebgp_multihop: int | UndefinedType = Undefined, + evpn_hostflap_detection: EvpnHostflapDetection | UndefinedType = Undefined, + evpn_import_pruning: bool | UndefinedType = Undefined, + evpn_multicast: bool | UndefinedType = Undefined, + evpn_overlay_bgp_rtc: bool | UndefinedType = Undefined, + evpn_prevent_readvertise_to_server: bool | UndefinedType = Undefined, + evpn_short_esi_prefix: str | UndefinedType = Undefined, + evpn_vlan_aware_bundles: bool | UndefinedType = Undefined, + evpn_vlan_bundles: EvpnVlanBundles | UndefinedType = Undefined, + fabric_evpn_encapsulation: Literal["vxlan", "mpls"] | None | UndefinedType = Undefined, + fabric_flow_tracking: FabricFlowTracking | UndefinedType = Undefined, + fabric_ip_addressing: FabricIpAddressing | UndefinedType = Undefined, + fabric_name: str | UndefinedType = Undefined, + fabric_sflow: FabricSflow | UndefinedType = Undefined, + flow_tracking_settings: FlowTrackingSettings | UndefinedType = Undefined, + generate_cv_tags: GenerateCvTags | UndefinedType = Undefined, + hardware_counters: HardwareCounters | UndefinedType = Undefined, + internal_vlan_order: InternalVlanOrder | UndefinedType = Undefined, + ipv4_acls: Ipv4Acls | UndefinedType = Undefined, + ipv4_prefix_list_catalog: Ipv4PrefixListCatalog | UndefinedType = Undefined, + ipv6_mgmt_destination_networks: Ipv6MgmtDestinationNetworks | UndefinedType = Undefined, + ipv6_mgmt_gateway: str | None | UndefinedType = Undefined, + is_deployed: bool | UndefinedType = Undefined, + isis_advertise_passive_only: bool | UndefinedType = Undefined, + isis_area_id: str | UndefinedType = Undefined, + isis_default_circuit_type: Literal["level-1-2", "level-1", "level-2"] | UndefinedType = Undefined, + isis_default_is_type: Literal["level-1-2", "level-1", "level-2"] | UndefinedType = Undefined, + isis_default_metric: int | UndefinedType = Undefined, + isis_maximum_paths: int | UndefinedType = Undefined, + isis_system_id_format: Literal["node_id", "underlay_loopback"] | UndefinedType = Undefined, + isis_ti_lfa: IsisTiLfa | UndefinedType = Undefined, + l3_edge: L3Edge | UndefinedType = Undefined, + l3_interface_profiles: L3InterfaceProfiles | UndefinedType = Undefined, + local_users: LocalUsers | UndefinedType = Undefined, + mac_address_table: MacAddressTable | UndefinedType = Undefined, + management_eapi: ManagementEapi | UndefinedType = Undefined, + mgmt_destination_networks: MgmtDestinationNetworks | UndefinedType = Undefined, + mgmt_gateway: str | None | UndefinedType = Undefined, + mgmt_interface: str | UndefinedType = Undefined, + mgmt_interface_description: str | UndefinedType = Undefined, + mgmt_interface_vrf: str | UndefinedType = Undefined, + mgmt_vrf_routing: bool | UndefinedType = Undefined, + mlag_bgp_peer_description: str | UndefinedType = Undefined, + mlag_bgp_peer_group_description: str | UndefinedType = Undefined, + mlag_ibgp_peering_vrfs: MlagIbgpPeeringVrfs | UndefinedType = Undefined, + mlag_member_description: str | UndefinedType = Undefined, + mlag_on_orphan_port_channel_downlink: bool | UndefinedType = Undefined, + mlag_peer_l3_svi_description: str | UndefinedType = Undefined, + mlag_peer_l3_vlan_name: str | UndefinedType = Undefined, + mlag_peer_l3_vrf_svi_description: str | UndefinedType = Undefined, + mlag_peer_l3_vrf_vlan_name: str | UndefinedType = Undefined, + mlag_peer_svi_description: str | UndefinedType = Undefined, + mlag_peer_vlan_name: str | UndefinedType = Undefined, + mlag_port_channel_description: str | UndefinedType = Undefined, + name_servers: NameServers | UndefinedType = Undefined, + network_ports: NetworkPorts | UndefinedType = Undefined, + network_services_keys: NetworkServicesKeys | UndefinedType = Undefined, + custom_node_type_keys: CustomNodeTypeKeys | UndefinedType = Undefined, + node_type_keys: NodeTypeKeys | UndefinedType = Undefined, + ntp_settings: NtpSettings | UndefinedType = Undefined, + only_local_vlan_trunk_groups: bool | UndefinedType = Undefined, + overlay_bgp_peer_description: str | UndefinedType = Undefined, + overlay_cvx_servers: OverlayCvxServers | UndefinedType = Undefined, + overlay_her_flood_list_per_vni: bool | UndefinedType = Undefined, + overlay_her_flood_list_scope: Literal["fabric", "dc"] | UndefinedType = Undefined, + overlay_loopback_description: str | None | UndefinedType = Undefined, + overlay_mlag_rfc5549: bool | UndefinedType = Undefined, + overlay_rd_type: OverlayRdType | UndefinedType = Undefined, + overlay_routing_protocol: Literal["ebgp", "ibgp", "cvx", "her", "none"] | None | UndefinedType = Undefined, + overlay_routing_protocol_address_family: Literal["ipv4", "ipv6"] | UndefinedType = Undefined, + overlay_rt_type: OverlayRtType | UndefinedType = Undefined, + p2p_uplinks_mtu: int | UndefinedType = Undefined, + p2p_uplinks_qos_profile: str | None | UndefinedType = Undefined, + custom_platform_settings: CustomPlatformSettings | UndefinedType = Undefined, + platform_settings: PlatformSettings | UndefinedType = Undefined, + platform_speed_groups: PlatformSpeedGroups | UndefinedType = Undefined, + pod_name: str | None | UndefinedType = Undefined, + port_profiles: PortProfiles | UndefinedType = Undefined, + ptp_profiles: PtpProfiles | UndefinedType = Undefined, + ptp_settings: PtpSettings | UndefinedType = Undefined, + queue_monitor_length: QueueMonitorLength | UndefinedType = Undefined, + redundancy: Redundancy | UndefinedType = Undefined, + router_id_loopback_description: str | UndefinedType = Undefined, + serial_number: str | None | UndefinedType = Undefined, + sflow_settings: SflowSettings | UndefinedType = Undefined, + shutdown_bgp_towards_undeployed_peers: bool | UndefinedType = Undefined, + shutdown_interfaces_towards_undeployed_peers: bool | UndefinedType = Undefined, + snmp_settings: SnmpSettings | UndefinedType = Undefined, + source_interfaces: SourceInterfaces | UndefinedType = Undefined, + svi_profiles: SviProfiles | UndefinedType = Undefined, + system_mac_address: str | None | UndefinedType = Undefined, + terminattr_disable_aaa: bool | UndefinedType = Undefined, + terminattr_ingestexclude: str | UndefinedType = Undefined, + terminattr_ingestgrpcurl_port: int | UndefinedType = Undefined, + terminattr_smashexcludes: str | UndefinedType = Undefined, + timezone: str | None | UndefinedType = Undefined, + trunk_groups: TrunkGroups | UndefinedType = Undefined, + type: str | None | UndefinedType = Undefined, + underlay_filter_peer_as: bool | UndefinedType = Undefined, + underlay_filter_redistribute_connected: bool | UndefinedType = Undefined, + underlay_ipv6: bool | UndefinedType = Undefined, + underlay_isis_authentication_key: str | None | UndefinedType = Undefined, + underlay_isis_authentication_mode: Literal["md5", "text"] | None | UndefinedType = Undefined, + underlay_isis_bfd: bool | UndefinedType = Undefined, + underlay_isis_instance_name: str | None | UndefinedType = Undefined, + underlay_l2_ethernet_description: str | UndefinedType = Undefined, + underlay_l2_port_channel_description: str | UndefinedType = Undefined, + underlay_multicast: bool | UndefinedType = Undefined, + underlay_multicast_anycast_rp: UnderlayMulticastAnycastRp | UndefinedType = Undefined, + underlay_multicast_rps: UnderlayMulticastRps | UndefinedType = Undefined, + underlay_ospf_area: str | UndefinedType = Undefined, + underlay_ospf_authentication: UnderlayOspfAuthentication | UndefinedType = Undefined, + underlay_ospf_bfd_enable: bool | UndefinedType = Undefined, + underlay_ospf_max_lsa: int | UndefinedType = Undefined, + underlay_ospf_process_id: int | UndefinedType = Undefined, + underlay_rfc5549: bool | UndefinedType = Undefined, + underlay_routing_protocol: Literal["ebgp", "ospf", "ospf-ldp", "isis", "isis-sr", "isis-ldp", "isis-sr-ldp", "none"] + | None + | UndefinedType = Undefined, + uplink_ptp: UplinkPtp | UndefinedType = Undefined, + use_cv_topology: bool | None | UndefinedType = Undefined, + use_router_general_for_router_id: bool | UndefinedType = Undefined, + vtep_loopback_description: str | UndefinedType = Undefined, + vtep_vvtep_ip: str | None | UndefinedType = Undefined, + wan_carriers: WanCarriers | UndefinedType = Undefined, + wan_encapsulation: Literal["path-selection", "vxlan"] | UndefinedType = Undefined, + wan_ha: WanHa | UndefinedType = Undefined, + wan_ipsec_profiles: WanIpsecProfiles | UndefinedType = Undefined, + wan_mode: Literal["autovpn", "cv-pathfinder"] | UndefinedType = Undefined, + wan_path_groups: WanPathGroups | UndefinedType = Undefined, + wan_route_servers: WanRouteServers | UndefinedType = Undefined, + wan_stun_dtls_disable: bool | UndefinedType = Undefined, + wan_stun_dtls_profile_name: str | UndefinedType = Undefined, + wan_virtual_topologies: WanVirtualTopologies | UndefinedType = Undefined, + zscaler_endpoints: ZscalerEndpoints | UndefinedType = Undefined, + _custom_data: dict[str, Any] | UndefinedType = Undefined, + _custom_structured_configurations: _CustomStructuredConfigurations | UndefinedType = Undefined, + _dynamic_keys: _DynamicKeys | UndefinedType = Undefined, + ) -> None: + """ + EosDesigns. + + + Subclass of AvdModel. + + Args: + application_classification: + Application traffic recognition configuration. + + Subclass of AvdModel. + avd_data_validation_mode: + Validation Mode for AVD input data validation. + Input data validation will validate the input + variables according to the schema. + During validation, messages will generated with information about + the host(s) and key(s) which failed validation. + "error" will produce error messages and fail the + task. + "warning" will produce warning messages. + avd_eos_designs_debug: Dump all vars and facts per device after generating `avd_switch_facts`. + avd_eos_designs_structured_config: Generate structured configuration per device. + avd_eos_designs_unset_facts: + Unset `avd_switch_facts` to gain a small performance improvement since Ansible needs to handle fewer + variables. + bfd_multihop: + BFD Multihop tuning. + + Subclass of AvdModel. + bgp_as: + BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>" to use to configure + overlay when "overlay_routing_protocol" == ibgp. + For asdot notation in YAML inputs, the value must + be put in quotes, to prevent it from being interpreted as a float number. + bgp_default_ipv4_unicast: + Default activation of IPv4 unicast address-family on all IPv4 neighbors. + It is best practice to + disable activation. + bgp_distance: Subclass of AvdModel. + bgp_ecmp: + Maximum ECMP for BGP multi-path. + The default value is 4 except for WAN Routers where the default + value is unset (falls back to EOS default). + bgp_graceful_restart: + BGP graceful-restart allows a BGP speaker with separate control plane and data plane processing to + continue forwarding traffic during a BGP restart. + Its neighbors (receiving speakers) may retain + routing information from the restarting speaker while a BGP session with it is being re-established, + reducing route flapping. + + + Subclass of AvdModel. + bgp_maximum_paths: + Maximum Paths for BGP multi-path. + The default value is 4 except for WAN Routers where the default + value is 16. + bgp_mesh_pes: + Configure an iBGP full mesh between PEs, either because there is no RR used or other reasons. + Only + supported in combination with MPLS overlay. + bgp_peer_groups: + Leverage an Arista EOS switch to generate the encrypted password using the correct peer group name. + Note that the name of the peer groups use '-' instead of '_' in EOS configuration. + + + Subclass of + AvdModel. + bgp_update_wait_install: + Do not advertise reachability to a prefix until that prefix has been installed in hardware. + This + will eliminate any temporary black holes due to a BGP speaker advertising reachability to a prefix + that may not yet be installed into the forwarding plane. + bgp_update_wait_for_convergence: + Disables FIB updates and route advertisement when the BGP instance is initiated until the BGP + convergence state is reached. + connected_endpoints_keys: + Endpoints connecting to the fabric can be grouped by using separate keys. + The keys can be customized + to provide a better better organization or grouping of your data. + `connected_endpoints_keys` should + be defined in the top level group_vars for the fabric. + The default values will be overridden if + defining this key, so it is recommended to copy the defaults and modify them. + + + Subclass of + AvdIndexedList with `ConnectedEndpointsKeysItem` items. Primary key is `key` (`str`). + core_interfaces: Subclass of AvdModel. + custom_structured_configuration_list_merge: + The List-merge strategy used when merging custom structured configurations. + + This applies to all + vars prefixed by prefixes in `custom_structured_configuration_prefix` + and all data under the various + `structured_config` options. + + The available list merge strategies: + - `replace`: + - Any list will be + replaced with the list defined in custom structured configurations. + - `append`: + - Existing list + items with the same "Primary key"-value will be updated. + - New items will be appended to the + existing list (including duplicates). + - `keep`: + - Only set list if there is no existing list or + existing list is `None`. + - `prepend`: + - Existing list items with the same "Primary key"-value will + be updated. + - New items will be prepended to the existing list (including duplicates). + - + `append_rp`: + - Existing list items with the same "Primary key"-value will be updated. + - New + unique items will be appended to the existing list. + - `prepend_rp`: + - Existing list items with the + same "Primary key"-value will be updated. + - New unique items will be prepended to the existing + list. + custom_structured_configuration_prefix: + Custom EOS Structured Configuration keys can be set on any group or host_var level using the name + of + the corresponding `eos_cli_config_gen` key prefixed with content of + `custom_structured_configuration_prefix`. + + The content of Custom Structured Configuration variables + will be merged with the structured config generated by the eos_designs role. + + The merge is done + recursively, so it is possible to update a sub-key of a variable set by `eos_designs` role already. + The merge follow these recursive merge strategies: + - New keys will be added for all types. + - + Existing keys of type "List" with a "Primary key" set in the schema: + - Strategy can be changed + with `custom_structured_configuration_list_merge`. Default strategy: + - Existing list items with + the same "Primary key"-value will be updated. + - New unique items will be appended to the + existing list + - Other keys of type "List" will have new unique items appended the the existing list. + - Existing keys of type "Dictionary" will recursively merge + - Other existing keys will be replaced. + Subclass of AvdList with `str` items. + cv_pathfinder_global_sites: + Define sites that are outside of the CV Pathfinder hierarchy. + This is used to arrange pathfinders in + the CloudVision topology layout. + + Subclass of AvdIndexedList with `CvPathfinderGlobalSitesItem` + items. Primary key is `name` (`str`). + cv_pathfinder_internet_exit_policies: + PREVIEW: These keys are in preview mode. + + List of internet-exit policies used for the WAN + configuration. + + Subclass of AvdIndexedList with `CvPathfinderInternetExitPoliciesItem` items. + Primary key is `name` (`str`). + cv_pathfinder_regions: + Define the CV Pathfinder hierarchy. + + Subclass of AvdIndexedList with `CvPathfinderRegionsItem` + items. Primary key is `name` (`str`). + cv_server: + PREVIEW: These keys are in preview mode. + + Hostname or IP address of CloudVision host. Ex. + "www.arista.io" for CVaaS. + For `eos_designs` this variable is only used for the WAN Internet-exit + integration with Zscaler. + The same variable name is also used by the `cv_deploy` role, and will + override the value of `ansible_host` on inventory 'cloudvision' host. + Make sure to set it in a + common group_vars file. + cv_tags_topology_type: + PREVIEW: This key is currently not supported + Device type that CloudVision should use when generating + the Topology. Defaults to the setting under node_type_keys. + cv_token: + PREVIEW: These keys are in preview mode. + + Service account token as defined on CloudVision. This + value should be using Ansible Vault. + For `eos_designs` this variable is only used for the WAN + Internet-exit integration with Zscaler. + The same variable name is also used by the `cv_deploy` role, + and will override the value of `ansible_password` on inventory 'cloudvision' host. + Make sure to set + it in a common group_vars file. + cv_topology: + Generate AVD configurations directly from the given CloudVision topology. + Activate this feature by + setting `use_cv_topology` to `true`. + Requires `default_interfaces` to be set for the relevant + platforms and node types to detect the proper interface roles automatically. + Neighbor hostnames must + match the inventory hostnames of the AVD inventory to be taken into consideration. + + Subclass of + AvdIndexedList with `CvTopologyItem` items. Primary key is `hostname` (`str`). + cvp_ingestauth_key: + On-premise CVP ingest auth key. If set, TerminAttr will be configured with key-based authentication + for on-premise CVP. + If not set, TerminAttr will be configured with certificate based authentication: + - On-premise using token onboarding. Default token path is '/tmp/token'. + - CVaaS using token-secure + onboarding. Default token path is '/tmp/cv-onboarding-token'. + Token must be copied to the device + first. + cvp_instance_ips: + List of IPv4 addresses or DNS names for CloudVision. + For on-premise CloudVision enter all the nodes + of the cluster. + For CloudVision as a Service enter the DNS name of the instance. + `eos_designs` only + supports one CloudVision cluster. + + + Subclass of AvdList with `str` items. + cvp_token_file: + cvp_token_file is the path to the token file on the switch. + If not set the default locations for on- + premise or CVaaS will be used. + See cvp_ingestauth_key for details. + dc_name: + DC Name is used in: + - Fabric Documentation (Optional, falls back to fabric_name) + - SNMP Location: + `snmp_settings.location` (Optional) + - HER Overlay DC scoped flood lists: + `overlay_her_flood_list_scope: dc` (Required) + default_connected_endpoints_description: + Default description or description template to be used on all ports to connected endpoints. + This can + be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `endpoint_type`: The `type` from + `connected_endpoints_keys` like `server`, `router` etc. + - `endpoint`: The name of the connected + endpoint + - `endpoint_port`: The value from `endpoint_ports` for this switch port if set. + - + `port_channel_id`: The port-channel number for the switch. + + By default the description is templated + from the type, name and port of the endpoint if set. + default_connected_endpoints_port_channel_description: + Default description or description template to be used on all port-channels to connected endpoints. + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `endpoint_type`: The `type` from + `connected_endpoints_keys` like `server`, `router` etc. + - `endpoint`: The name of the connected + endpoint + - `endpoint_port_channel`: The value of `endpoint_port_channel` if set. + - + `port_channel_id`: The port-channel number for the switch. + - `adapter_description`: The adapter's + description if set. + - `adapter_description_or_endpoint`: Helper alias of the adapter_description + or endpoint. + + By default the description is templated from the type, name and port-channel name of + the endpoint if set. + default_igmp_snooping_enabled: When set to false, disables IGMP snooping at fabric level and overrides per vlan settings. + default_interface_mtu: + Default interface MTU configured on EOS under "interface defaults". + Can be overridden per platform + under platform settings. + default_interfaces: + Default uplink, downlink, and MLAG interfaces, which will be used if these interfaces are not + defined on a device (either directly or through inheritance). + + + Subclass of AvdList with + `DefaultInterfacesItem` items. + default_mgmt_method: + `default_mgmt_method` controls the default VRF and source interface used for the following + management and monitoring protocols configured with `eos_designs`: + - `ntp_settings` + - + `sflow_settings` + + `oob` means the protocols will be configured with the VRF set by + `mgmt_interface_vrf` and `mgmt_interface` as the source interface. + `inband` means the protocols will + be configured with the VRF set by `inband_mgmt_vrf` and `inband_mgmt_interface` as the source + interface. + `none` means the VRF and or interface must be manually set for each protocol. + This can be + overridden under the settings for each protocol. + default_network_ports_description: + Default description or description template to be used on all ports defined under `network_ports`. + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `endpoint_type`: Always set to + `network_port`. + - `endpoint`: The value of the `endpoint` key if set. + - `port_channel_id`: The + port-channel number for the switch. + + By default the description is templated from the `endpoint` key + if set. + default_network_ports_port_channel_description: + Default description or description template to be used on all port-channels defined under + `network_ports`. + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `endpoint_type`: Always set to + `network_port`. + - `endpoint`: The value of the `endpoint` key if set. + - `endpoint_port_channel`: + The value of `endpoint_port_channel` if set. + - `port_channel_id`: The port-channel number for the + switch. + - `adapter_description`: The adapter's description if set. + - + `adapter_description_or_endpoint`: Helper alias of the adapter_description or endpoint. + + By default + the description is templated from the `endpoint` key if set. + default_node_types: + Uses hostname matches against a regular expression to determine the node type. + + Subclass of + AvdIndexedList with `DefaultNodeTypesItem` items. Primary key is `node_type` (`str`). + default_underlay_p2p_ethernet_description: + The default description or description template to be used on L3 point-to-point ethernet interfaces. + The interfaces using this are the routed uplinks and `p2p_links` defined under `l3_edge` or + `core_interfaces`. + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `peer`: The name of the peer. + - + `interface`: The local interface name. + - `peer_interface`: The interface on the peer. + - `vrf`: + The name of the VRF if set (Only applicable for `uplink_type: p2p-vrfs`). + + By default the + description is templated from the name and interface of the peer. + default_underlay_p2p_port_channel_description: + The default description or description template to be used on L3 point-to-point port-channel + interfaces. + The port-channels using this are `p2p_links` defined under `l3_edge` or + `core_interfaces`. + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `peer`: The name of the peer. + - + `interface`: The local interface name. + - `peer_interface`: The interface on the peer. + - + `port_channel_id`: The local port-channel ID. + - `peer_port_channel_id`: The ID of the port-channel + on the peer. + + By default the description is templated from the name and interface of the peer. + default_vrf_diag_loopback_description: + The default description or description template to be used on VRF diagnostic loopback interfaces. + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `interface`: The Loopback interface + name. + - `vrf`: The VRF name. + - `tenant`: The tenant name. + + By default the description is + templated from the VRF name. + design: Subclass of AvdModel. + enable_trunk_groups: + Enable Trunk Group support across eos_designs. + Warning: Because of the nature of the EOS Trunk Group + feature, enabling this is "all or nothing". + *All* vlans and *all* trunks towards connected endpoints + must be using trunk groups as well. + If trunk groups are not assigned to a trunk, no vlans will be + enabled on that trunk. + See "Details on enable_trunk_groups" below before enabling this feature. + eos_designs_custom_templates: Subclass of AvdList with `EosDesignsCustomTemplatesItem` items. + eos_designs_documentation: + Control fabric documentation generation. + + + Subclass of AvdModel. + event_handlers: + Gives the ability to monitor and react to Syslog messages. + Event Handlers provide a powerful and + flexible tool that can be used to apply self-healing actions, + customize the system behavior, and + implement workarounds to problems discovered in the field. + evpn_ebgp_gateway_inter_domain: evpn_ebgp_gateway_inter_domain + evpn_ebgp_gateway_multihop: + Default of 15, considering a large value to avoid BGP reachability issues in very complex DCI + networks. + Adapt the value for your specific topology. + evpn_ebgp_multihop: + Default of 3, the recommended value for a 3 stage spine and leaf topology. + Set to a higher value to + allow for very large and complex topologies. + evpn_hostflap_detection: Subclass of AvdModel. + evpn_import_pruning: + Enable VPN import pruning (Min. EOS 4.24.2F). + The Route Target extended communities carried by + incoming VPN paths will be examined. + If none of those Route Targets have been configured for import, + the path will be immediately discarded. + evpn_multicast: + General Configuration required for EVPN Multicast. "evpn_l2_multicast" or "evpn_l3_multicast" must + also be configured under the Network Services (tenants). + Requires "underlay_multicast: true" and + IGMP snooping enabled globally (default). + For MLAG devices Route Distinguisher must be unique since + this feature will create multi-vtep configuration. + Warning !!! For Trident3 based platforms i.e + 7050X3, 7300X3, 720XP. + The Following default platform setting will be configured on 7050X3 and + 7300X3: "platform trident forwarding-table partition flexible exact-match 16384 l2-shared 98304 + l3-shared 131072" + The Following default platform setting will be configured on 720XP: "flexible + exact-match 16000 l2-shared 18000 l3-shared 22000" + All forwarding agents will be restarted when + this configuration is applied. + You can tune the settings by overriding the default variable: + "platform_settings[platforms].trident_forwarding_table_partition:" + Please contact an Arista + representative for help with determining the appropriate values for your environment. + evpn_overlay_bgp_rtc: + Enable Route Target Membership Constraint Address Family on EVPN overlay BGP peerings (Min. EOS + 4.25.1F). + Requires use eBGP as overlay protocol. + evpn_prevent_readvertise_to_server: + Configure route-map on eBGP sessions towards route-servers, where prefixes with the peer's ASN in + the AS Path are filtered away. + This is very useful in large-scale networks, where convergence will + be quicker by not returning all updates received + from Route-server-1 to Router-server-2 just for + Route-server-2 to throw them away because of AS Path loop detection. + evpn_short_esi_prefix: Configure prefix for "short_esi" values. + evpn_vlan_aware_bundles: + Enable VLAN aware bundles for every EVPN MAC-VRF. + If set to `true` all SVIs in a VRF are configured + in a vlan-aware-bundle using the VRF name as the bundle name. `l2vlans` are bundled in vlan-aware- + bundles using the VLAN name as the bundle name. + + The `evpn_vlan_bundle` option under `svis` and + `l2vlans` takes precedence and overrides this behavior. Per svi/l2vlan `evpn_vlan_bundle` also works + when this setting is disabled which allow mixing vlan-aware-bundles with regular MAC-VRFs. + evpn_vlan_bundles: Subclass of AvdIndexedList with `EvpnVlanBundlesItem` items. Primary key is `name` (`str`). + fabric_evpn_encapsulation: + Should be set to mpls for evpn-mpls scenario. This overrides the evpn_encapsulation setting under + node_type_keys. + fabric_flow_tracking: + Default enabling of flow-tracking(IPFIX) for various interface types across the fabric. + Flow + Tracking can also be enabled/disabled under each of the specific data models. + For general flow- + tracking settings see `flow_tracking_settings`. + + Subclass of AvdModel. + fabric_ip_addressing: Subclass of AvdModel. + fabric_name: + Fabric Name, required to match Ansible Group name covering all devices in the Fabric, **must** be an + inventory group name. + fabric_sflow: + Default enabling of sFlow for various interface types across the fabric. + sFlow can also be + enabled/disabled under each of the specific data models. + For general sFlow settings see + `sflow_settings`. + + Subclass of AvdModel. + flow_tracking_settings: + Define the flow tracking parameters for this topology. + + Subclass of AvdModel. + generate_cv_tags: + PREVIEW: This key is currently not supported + Generate CloudVision Tags based on AVD data. + + Subclass + of AvdModel. + hardware_counters: Subclass of AvdModel. + internal_vlan_order: + Internal vlan allocation order and range. + + Subclass of AvdModel. + ipv4_acls: + IPv4 extended access-lists supporting substitution on certain fields. + These access-lists can be + referenced under node settings `l3_interfaces`, and will only be configured on devices where they + are in use. + + The substitution is useful when assigning the same access-list on multiple interfaces, + but where certain fields require unique values like the "interface_ip" or "peer_ip". + When using + substitution, the interface name will be appended to the ACL name. + + Subclass of AvdIndexedList with + `Ipv4AclsItem` items. Primary key is `name` (`str`). + ipv4_prefix_list_catalog: + IPv4 prefix-list catalog. + + Subclass of AvdIndexedList with `Ipv4PrefixListCatalogItem` items. + Primary key is `name` (`str`). + ipv6_mgmt_destination_networks: + List of IPv6 prefixes to configure as static routes towards the OOB IPv6 Management interface + gateway. + Replaces the default route. + + + Subclass of AvdList with `str` items. + ipv6_mgmt_gateway: + OOB Management interface gateway in IPv6 format. + Used as next-hop for default gateway or static + routes defined under 'ipv6_mgmt_destination_networks'. + is_deployed: + If the device is already deployed in the fabric. + When set to false, interfaces toward this device + may be shutdown depending on the `shutdown_interfaces_towards_undeployed_peers` setting. + Furthermore + `eos_config_deploy_cvp` will not attempt to move or apply configurations to the device. + isis_advertise_passive_only: isis_advertise_passive_only + isis_area_id: isis_area_id + isis_default_circuit_type: + These fabric level parameters can be used with core_interfaces running ISIS, and may be overridden + on link profile or link level. + isis_default_is_type: isis_default_is_type + isis_default_metric: + These fabric level parameters can be used with core_interfaces running ISIS, and may be overridden + at link profile or link level. + isis_maximum_paths: Number of path to configure in ECMP for ISIS. + isis_system_id_format: + Configures source for the system-id within the ISIS net id. + If this key is set to `node_id`, the + fields `id` and `isis_system_id_prefix` configured under the node attributes are used to generate + the system-id. + If `underlay_loopback` is selected then all node `isis_system_id_prefix` settings + will be ignored and the loopback address will be used to generate the system-id. + isis_ti_lfa: Subclass of AvdModel. + l3_edge: Subclass of AvdModel. + l3_interface_profiles: + Profiles to inherit common settings for l3_interfaces defined under the node type key. + These + profiles will *not* work for `l3_interfaces` defined under `vrfs`. + + Subclass of AvdIndexedList with + `L3InterfaceProfilesItem` items. Primary key is `profile` (`str`). + local_users: local_users + mac_address_table: + MAC address-table aging time. + Use to change the EOS default of 300. + + + Subclass of AvdModel. + management_eapi: + Default is HTTPS management eAPI enabled. + The VRF is set to < mgmt_interface_vrf >. + + + Subclass of + AvdModel. + mgmt_destination_networks: + List of IPv4 prefixes to configure as static routes towards the OOB Management interface gateway. + Replaces the default route. + + Subclass of AvdList with `str` items. + mgmt_gateway: + OOB Management interface gateway in IPv4 format. + Used as next-hop for default gateway or static + routes defined under 'mgmt_destination_networks'. + mgmt_interface: OOB Management interface. + mgmt_interface_description: Management interface description. + mgmt_interface_vrf: OOB Management VRF. + mgmt_vrf_routing: Configure IP routing for the OOB Management VRF. + mlag_bgp_peer_description: + Description or description template to be used on the MLAG BGP peers including those in VRFs. + This + can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `mlag_peer`: The name of the MLAG + peer. + - `interface`: The local MLAG L3 VLAN interface. + - `peer_interface`: The MLAG L3 VLAN + interface on the MLAG peer. + - `vrf`: The name of the VRF. Not available for the underlay peering. + The default description is built from the name and interface of the MLAG peer and optionally the + VRF. + mlag_bgp_peer_group_description: + Description or description template to be used on the MLAG BGP peer-group. + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `mlag_peer`: The name of the MLAG peer. + + The default description is the name of the MLAG peers. + mlag_ibgp_peering_vrfs: + On mlag leafs, an SVI interface is defined per vrf, to establish iBGP peering (required when there + are MLAG leafs in topology). + The SVI id will be derived from the base vlan defined: + mlag_ibgp_peering_vrfs.base_vlan + (vrf_id or vrf_vni) - 1. + Depending on the values of vrf_id / + vrf_vni it may be required to adjust the base_vlan to avoid overlaps or invalid vlan ids. + The SVI ip + address derived from mlag_l3_peer_ipv4_pool is re-used across all iBGP peerings. + + + Subclass of + AvdModel. + mlag_member_description: + Description or description template to be used on MLAG peer-link ethernet interfaces. + This can be a + template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `mlag_peer`: The name of the MLAG + peer. + - `interface`: The local MLAG port-channel interface. + - `peer_interface`: The port-channel + interface on the MLAG peer. + - `mlag_port_channel_id`: The local MLAG port-channel ID. + - + `mlag_peer_port_channel_id`: The port-channel ID on the MLAG peer. + + By default the description is + templated from the name and interface of the MLAG peer. + mlag_on_orphan_port_channel_downlink: + If `true` an MLAG ID will always be configured on a Port-Channel downlink even if the downlink is + only on one node in the MLAG pair. + If `false` (default) an MLAG ID will only be configured on Port- + Channel downlinks dual-homed to two MLAG switches. + mlag_peer_l3_svi_description: + Description or description template to be used on MLAG L3 peering SVI (Interface Vlan4093 by + default). + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `mlag_peer`: The name of the MLAG + peer. + - `interface`: The MLAG L3 peering SVI name. + - `mlag_peer_l3_vlan`: The MLAG L3 peering + VLAN ID. + mlag_peer_l3_vlan_name: + Name or name template to be used on MLAG L3 VLAN (VLAN 4093 by default). + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `mlag_peer`: The name of the MLAG peer. + - `mlag_peer_l3_vlan`: The MLAG L3 peering VLAN ID. + mlag_peer_l3_vrf_svi_description: + Description or description template to be used on MLAG L3 peering SVI for VRFs. + This can be a + template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `mlag_peer`: The name of the MLAG + peer. + - `interface`: The MLAG L3 VRF peering SVI name. + - `vlan`: The MLAG L3 VRF peering VLAN + ID. + - `vrf`: The VRF name. + mlag_peer_l3_vrf_vlan_name: + Name or name template to be used on MLAG L3 peering VLAN for VRFs. + This can be a template using the + AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom- + descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - + `mlag_peer`: The name of the MLAG peer. + - `vlan`: The MLAG L3 VRF peering VLAN ID. + - `vrf`: The + VRF name. + mlag_peer_svi_description: + Description or description template to be used on MLAG peering SVI (Interface Vlan4094 by default). + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `mlag_peer`: The name of the MLAG + peer. + - `interface`: The MLAG peering SVI name. + - `mlag_peer_vlan`: The MLAG peering VLAN ID. + mlag_peer_vlan_name: + Name or name template to be used on MLAG peering VLAN (VLAN 4094 by default). + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `mlag_peer`: The name of the MLAG peer. + - `mlag_peer_vlan`: The MLAG peering VLAN ID. + mlag_port_channel_description: + Description or description template to be used on MLAG peer-link port-channel interfaces. + This can + be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `mlag_peer`: The name of the MLAG + peer. + - `interface`: The local MLAG port-channel interface. + - `peer_interface`: The port-channel + interface on the MLAG peer. + - `mlag_port_channel_id`: The local MLAG port-channel ID. + - + `mlag_peer_port_channel_id`: The port-channel ID on the MLAG peer. + + By default the description is + templated from the name and port-channel interface of the MLAG peer. + name_servers: + List of DNS servers. The VRF is set to < mgmt_interface_vrf >. + + Subclass of AvdList with `str` + items. + network_ports: Subclass of AvdList with `NetworkPortsItem` items. + network_services_keys: + Network Services can be grouped by using separate keys. + The keys can be customized to provide a + better better organization or grouping of your data. + `network_services_keys` should be defined in + the top level group_vars for the fabric. + The default values will be overridden if defining this key, + so it is recommended to copy the defaults and modify them. + + + Subclass of AvdIndexedList with + `NetworkServicesKeysItem` items. Primary key is `name` (`str`). + custom_node_type_keys: + Define Custom Node Type Keys, to specify the properties of each node type in the fabric. + This allows + for complete customization of the fabric layout and functionality. + `custom_node_type_keys` should be + defined in top level group_var for the fabric. + These values will be combined with the defaults; + custom node type keys named the same as a + default node_type_key will replace the default. + + Subclass + of AvdIndexedList with `CustomNodeTypeKeysItem` items. Primary key is `key` (`str`). + node_type_keys: + Define Node Type Keys, to specify the properties of each node type in the fabric. + This allows for + complete customization of the fabric layout and functionality. + `node_type_keys` should be defined in + top level group_var for the fabric. + + The default values will be overridden if this key is defined. + If you need to change all the existing `node_type_keys`, it is recommended to copy the defaults and + modify them. + If you need to add custom `node_type_keys`, create them under `custom_node_type_keys` - + if named identically to default `node_type_keys` entries, + custom entries will replace the equivalent + default entry. + + Subclass of AvdIndexedList with `NodeTypeKeysItem` items. Primary key is `key` + (`str`). + ntp_settings: + NTP settings + + Subclass of AvdModel. + only_local_vlan_trunk_groups: + A vlan can have many trunk_groups assigned. + To avoid unneeded configuration changes on all leaf + switches when a new trunk group is added, + this feature will only configure the vlan trunk groups + matched with local connected_endpoints. + See "Details on only_local_vlan_trunk_groups" below. + Requires "enable_trunk_groups: true". + overlay_bgp_peer_description: + Description or description template to be used on the overlay BGP peers. + This can be a template + using the AVD string formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how- + to/custom-descriptions-names.html#avd-string-formatter-syntax. + The available template fields are: + - `peer`: The name of the BGP peer. + - `peer_interface`: The interface on the BGP peer if + available. + + The default description is built from the name and interface of the BGP peer. + overlay_cvx_servers: + List of CVX vxlan overlay controllers. + Required if overlay_routing_protocol == CVX. + CVX servers + (VMs) are peering using their management interface, so mgmt_ip must be set for all CVX servers. + Subclass of AvdList with `str` items. + overlay_her_flood_list_per_vni: + When using Head-End Replication, configure flood-lists per VNI. + By default HER will be configured + with a common flood-list containing all VTEPs. + This behavior can be changed to per-VNI flood-lists + by setting `overlay_her_flood_list_per_vni: true`. + This will make `eos_designs` consider configured + VLANs per VTEP, and only include the relevant VTEPs to each VNI's flood-list. + overlay_her_flood_list_scope: + When using Head-End Replication, set the scope of flood-lists to Fabric or DC. + By default all VTEPs + in the Fabric (part of the inventory group referenced by "fabric_name") are added to the flood- + lists. + This can be changed to all VTEPs in the DC (sharing the same "dc_name" value). + This is useful + if Border Leaf switches are dividing the VXLAN overlay into separate domains. + overlay_loopback_description: Customize the description on overlay interface Loopback0. + overlay_mlag_rfc5549: + IPv6 Unnumbered for MLAG iBGP connections. + Requires "underlay_rfc5549: true". + overlay_rd_type: + Configuration options for the Administrator subfield (first part of RD) and the Assigned Number + subfield (second part of RD). + + By default Route Distinguishers (RD) are set to: + - + `:` for VLANs and VLAN- + Aware Bundles with L2 vlans. + - `:` for + VLAN-Aware Bundles with SVIs. + - `:` for VLAN- + Aware Bundles defined under 'evpn_vlan_bundles'. + - `:` for VRFs. + + Note: # fmt: skip + RD + is a 48-bit value which is split into <16-bit>:<32-bit> or <32-bit>:<16-bit>. + When using loopback or + 32-bit ASN/number the assigned number can only be a 16-bit number. This may be a problem with large + VNIs. + For 16-bit ASN/number the assigned number can be a 32-bit number. + + + Subclass of AvdModel. + overlay_routing_protocol: + - The following overlay routing protocols are supported: + - ebgp: Configures fabric with eBGP, + default for l3ls-evpn design. + - ibgp: Configured fabric with iBGP, only supported with OSPF or + ISIS variants in underlay, default for mpls design. + - cvx: Configures fabric to leverage + CloudVision eXchange as the overlay controller. + - her: Configures fabric with Head-End + Replication, configures static VXLAN flood-lists instead of using a dynamic overlay protocol. + - + none: No overlay configuration will be generated, default for l2ls design. + + If not set, the + default_overlay_routing_protocol defined under the node_type_keys will be used (default is "ebgp"). + overlay_routing_protocol_address_family: + When set to `ipv6`, enable overlay EVPN peering with IPv6 addresses. + This feature depends on + underlay_ipv6 variable. As of today, only RFC5549 is capable to transport IPv6 in the underlay. + overlay_rt_type: + Configuration options for the Administrator subfield (first part of RT) and the Assigned Number + subfield (second part of RT). + + By default Route Targets (RT) are set to: + - `<(mac_vrf_id_base or + mac_vrf_vni_base) + vlan_id>:<(mac_vrf_id_base or mac_vrf_vni_base) + vlan_id>` for VLANs and VLAN- + Aware Bundles with L2 vlans. + - `:` for VLAN-Aware Bundles with SVIs. + - + `:` for VLAN-Aware Bundles + defined under 'evpn_vlan_bundles'. + - `:` for VRFs. + + Notes: # fmt: skip + RT is a 48-bit value + which is split into <16-bit>:<32-bit> or <32-bit>:<16-bit>. + When using 32-bit ASN/number the VNI can + only be a 16-bit number. Alternatively use vlan_id/vrf_id as assigned number. + For 16-bit ASN/number + the assigned number can be a 32-bit number. + + + Subclass of AvdModel. + p2p_uplinks_mtu: + Point to Point Links MTU. + Precedence: .uplink_mtu -> platform_settings.p2p_uplinks_mtu -> + p2p_uplinks_mtu -> 9214 + p2p_uplinks_qos_profile: QOS Profile assigned on all infrastructure links. + custom_platform_settings: + Custom Platform settings to override the default `platform_settings`. This list will be prepended to + the list of `platform_settings`. The first entry containing `platforms` matching the `platform` node + setting will be chosen. If no matches are found, the first entry containing a platform `default` + will be chosen. + + Subclass of AvdList with `CustomPlatformSettingsItem` items. + platform_settings: + Platform settings. The first entry containing `platforms` matching the `platform` node setting will + be chosen. If no matches are found, the first entry containing a platform `default` will be chosen. + The default values will be overridden if `platform_settings` is defined. If you need to replace all + the default platforms, it is recommended to copy the defaults and modify them. If you need to add + custom platforms, create them under `custom_platform_settings`. Entries under + `custom_platform_settings` will be matched before the equivalent entries from `platform_settings`. + Subclass of AvdList with `PlatformSettingsItem` items. + platform_speed_groups: + Set Hardware Speed Groups per Platform. + + Subclass of AvdIndexedList with `PlatformSpeedGroupsItem` + items. Primary key is `platform` (`str`). + pod_name: + POD Name is used in: + - Fabric Documentation (Optional, falls back to dc_name and then to + fabric_name) + - SNMP Location: `snmp_settings.location` (Optional) + - VRF Loopbacks: + `vtep_diagnostic.loopback_ip_pools.pod` (Required) + + Recommended to be common between Spines and + Leafs within a POD (One l3ls topology). + port_profiles: + Optional profiles to share common settings for connected_endpoints and/or network_ports. + Keys are + the same used under endpoints adapters. Keys defined under endpoints adapters take precedence. + Subclass of AvdIndexedList with `PortProfilesItem` items. Primary key is `profile` (`str`). + ptp_profiles: Subclass of AvdIndexedList with `PtpProfilesItem` items. Primary key is `profile` (`str`). + ptp_settings: + Common PTP settings. + + Subclass of AvdModel. + queue_monitor_length: Subclass of AvdModel. + redundancy: + Redundancy for chassis platforms with dual supervisors | Optional. + + Subclass of AvdModel. + router_id_loopback_description: Customize the description on Router ID interface Loopback0. + serial_number: + Serial Number of the device. + Used for documentation purpose in the fabric documentation as can also + be used by the 'eos_config_deploy_cvp' role. + "serial_number" can also be set directly under node + type settings. + If both are set, the value under node type settings takes precedence. + sflow_settings: + sFlow settings. + The sFlow process will only be configured if any interface is enabled for sFlow. + For + default enabling of sFlow for various interface types across the fabric see `fabric_sflow`. + Subclass of AvdModel. + shutdown_bgp_towards_undeployed_peers: + When a device is set undeployed using `is_deployed: false` and + `shutdown_bgp_towards_undeployed_peers` key is set to true, the BGP neighborship is shutdown on the + peer. + shutdown_interfaces_towards_undeployed_peers: + - It is possible to provision configurations for a complete topology but flag devices as undeployed + using the host level variable `is_deployed: false`. + + ```yaml + # Use at the host level + is_deployed: < + true or false or default -> true > + ``` + + - By default, this will have no impact within the + `eos_designs` role. Configs will still be generated by the `eos_cli_config_gen` role and will still + be pushed by the `eos_config_deploy_eapi` directly to devices if used. + - However, if the + `eos_config_deploy_cvp` role is used to push configurations, CloudVision will ignore the devices + flagged as `is_deployed: false` and not attempt to configure them. + - If the device is not present + in the network due to CloudVision not configuring the device, `eos_validate_state` role will fail + tests on peers of the undeployed device trying to verify that interfaces are up. + - To overcome this + and shutdown interfaces towards undeployed peers, the variable + `shutdown_interfaces_towards_undeployed_peers` can be used, satisfying the `eos_validate_state` role + interface tests. + - Again, this is only an issue if `eos_config_deploy_cvp` is used and the devices + are not present in the network. + snmp_settings: + SNMP settings. + For SNMP local-interfaces see "source_interfaces.snmp". + Configuration of remote SNMP + engine IDs are currently only possible using `structured_config`. + + Subclass of AvdModel. + source_interfaces: + Configure source-interfaces based on the management interfaces set for other `eos_designs` data + models. + By default, no source-interfaces will be configured. They can still be configured manually + using `eos_cli_config_gen` and custom structured configuration. + EOS supports a single source- + interface per VRF, so an error will be raised in case of conflicts. + Errors will also be raised if an + interface is not found for a device. + + Subclass of AvdModel. + svi_profiles: + Profiles to share common settings for SVIs under `.[].vrfs.svis`. + Keys are the + same used under SVIs. Keys defined under SVIs take precedence. + Note: structured configuration is not + merged recursively and will be taken directly from the most specific level in the following order: + 1. svi.nodes[inventory_hostname].structured_config + 2. + svi_profile.nodes[inventory_hostname].structured_config + 3. + svi_parent_profile.nodes[inventory_hostname].structured_config + 4. svi.structured_config + 5. + svi_profile.structured_config + 6. svi_parent_profile.structured_config + + + Subclass of AvdIndexedList + with `SviProfilesItem` items. Primary key is `profile` (`str`). + system_mac_address: + Set to the same MAC address as available in "show version" on the device. + "system_mac_address" can + also be set under node type settings. + If both are set, the value under node type settings takes + precedence. + terminattr_disable_aaa: terminattr_disable_aaa + terminattr_ingestexclude: terminattr_ingestexclude + terminattr_ingestgrpcurl_port: + Port number used for Terminattr connection to an on-premise CloudVision cluster. + The port number is + always 443 when using CloudVision as a Service, so this value is ignored. + terminattr_smashexcludes: terminattr_smashexcludes + timezone: Clock timezone like "CET" or "US/Pacific". + trunk_groups: Subclass of AvdModel. + type: + The `type:` variable needs to be defined for each device in the fabric. + This is leveraged to load + the appropriate template to generate the configuration. + underlay_filter_peer_as: + Configure route-map on eBGP sessions towards underlay peers, where prefixes with the peer's ASN in + the AS Path are filtered away. + This is very useful in very large scale networks not using EVPN + overlays, where convergence will be quicker by not having to return + all updates received from + Spine-1 to Spine-2 just for Spine-2 to throw them away because of AS Path loop detection. + Note that + this setting cannot be used while there are EVPN services present in the default VRF. + underlay_filter_redistribute_connected: + Filter redistribution of connected into the underlay routing protocol. + Only applicable when + overlay_routing_protocol != 'none' and underlay_routing_protocol == BGP. + Creates a route-map and + prefix-list assigned to redistribute connected permitting only loopbacks and inband management + subnets. + underlay_ipv6: + This feature allows IPv6 underlay routing protocol with RFC5549 addresses to be used along with IPv4 + advertisements as VXLAN tunnel endpoints. + Requires "underlay_rfc5549: true" and "loopback_ipv6_pool" + under the node type settings. + underlay_isis_authentication_key: Type-7 encrypted password. + underlay_isis_authentication_mode: Underlay ISIS authentication mode. + underlay_isis_bfd: Enable BFD for ISIS on all underlay links. + underlay_isis_instance_name: Default -> "EVPN_UNDERLAY" for l3ls, "CORE" for mpls. + underlay_l2_ethernet_description: + The description or description template to be used on L2 ethernet interfaces. + The interfaces using + this are the member interfaces of port-channel uplinks. + This can be a template using the AVD string + formatter syntax: https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions- + names.html#avd-string-formatter-syntax. + The available template fields are: + - `peer`: The name of + the peer. + - `interface`: The local interface name. + - `peer_interface`: The interface on the + peer. + + By default the description is templated from the hostname and interface of the peer. + underlay_l2_port_channel_description: + The description or description template to be used on L2 port-channel interfaces. + The interfaces + using this are port-channel uplinks. + This can be a template using the AVD string formatter syntax: + https://avd.arista.com/devel/roles/eos_designs/docs/how-to/custom-descriptions-names.html#avd- + string-formatter-syntax. + The available template fields are: + - `peer`: The name of the peer. + - + `interface`: The local interface name. + - `peer_interface`: The interface on the peer. + - + `port_channel_id`: The local port-channel ID. + - `peer_port_channel_id`: The ID of the port-channel + on the peer. + - `peer_node_group`: The node group of the peer if the peer is an MLAG member or + running EVPN A/A. + - `peer_node_group_or_peer`: Helper alias of the peer_node_group or peer. + - + `peer_node_group_or_uppercase_peer`: Helper alias of the peer_node_group or peer hostname in + uppercase. + + By default the description is templated from the peer's node group (for MLAG or EVPN + A/A) or hostname and port-channel interface of the peer. + underlay_multicast: + Enable Multicast in the underlay on all p2p uplink interfaces and mlag l3 peer interface. + Specifically PIM Sparse-Mode will be configured on all routed underlay interfaces. + No other + configuration is added, so the underlay will only support Source-Specific Multicast (SSM). + The + configuration is intended to be used as multicast underlay for EVPN OISM overlay. + underlay_multicast_anycast_rp: + If multiple nodes are configured under 'underlay_multicast_rps.[].nodes' for the same RP address, + they will be configured + with one of the following methods: + - Anycast RP using PIM (RFC4610). + - + Anycast RP using MSDP (RFC4611). + + NOTE: When using MSDP, all nodes across all MSDP enabled RPs will + be added to a single MSDP mesh group named "ANYCAST-RP". + + + Subclass of AvdModel. + underlay_multicast_rps: + List of PIM Sparse-Mode Rendevouz Points configured for underlay multicast on all devices. + The + device(s) listed under 'nodes', will be configured as the Rendevouz point router(s). + If multiple + nodes are configured under 'nodes' for the same RP address, they will be configured + according to the + 'underlay_multicast_anycast_rp.mode' setting. + + Requires 'underlay_multicast: true'. + + + Subclass of + AvdIndexedList with `UnderlayMulticastRpsItem` items. Primary key is `rp` (`str`). + underlay_ospf_area: underlay_ospf_area + underlay_ospf_authentication: Subclass of AvdModel. + underlay_ospf_bfd_enable: underlay_ospf_bfd_enable + underlay_ospf_max_lsa: underlay_ospf_max_lsa + underlay_ospf_process_id: underlay_ospf_process_id + underlay_rfc5549: + Point to Point Underlay with RFC 5549(eBGP), i.e. IPv6 Unnumbered. + Requires + "underlay_routing_protocol: ebgp". + underlay_routing_protocol: + - The following underlay routing protocols are supported: + - EBGP (default for l3ls-evpn) + - OSPF. + - OSPF-LDP*. + - ISIS. + - ISIS-SR*. + - ISIS-LDP*. + - ISIS-SR-LDP*. + - No underlay routing + protocol (none) + - The variables should be applied to all devices in the fabric. + *Only supported with + core_interfaces data model. + uplink_ptp: + Enable PTP on all infrastructure links. + + Subclass of AvdModel. + use_cv_topology: + Generate AVD configurations directly from a given CloudVision topology. + See `cv_topology` for + details. + use_router_general_for_router_id: Use `router general` to set router ID for all routing protocols and VRFs. + vtep_loopback_description: Customize the description on the VTEP interface, typically Loopback1. + vtep_vvtep_ip: + IP Address used as Virtual VTEP. Will be configured as secondary IP on Loopback1. + This is only + needed for centralized routing designs. + wan_carriers: + List of carriers used for the WAN configuration and their mapping to path-groups. + + Subclass of + AvdIndexedList with `WanCarriersItem` items. Primary key is `name` (`str`). + wan_encapsulation: Select the encapsulation to use for EVPN peerings for WAN BGP peers. + wan_ha: + PREVIEW: The `wan_ha` key is currently not supported. + + Subclass of AvdModel. + wan_ipsec_profiles: + Define IPsec profiles parameters for WAN configuration. + + Subclass of AvdModel. + wan_mode: Select if the WAN should be run using CV Pathfinder or AutoVPN only. + wan_path_groups: + List of path-groups used for the WAN configuration. + + Subclass of AvdIndexedList with + `WanPathGroupsItem` items. Primary key is `name` (`str`). + wan_route_servers: + List of the AutoVPN RRs when using `wan_mode: autovpn`, or the Pathfinders + when using `wan_mode: cv- + pathfinder`, to which the device should connect to. + This is also used to establish iBGP sessions + between WAN route servers. + + When the route server is part of the same inventory as the WAN routers, + only the name is required. + + Subclass of AvdIndexedList with `WanRouteServersItem` items. Primary key + is `hostname` (`str`). + wan_stun_dtls_disable: + WAN STUN connections are authenticated and secured with DTLS by default. + For CV Pathfinder + deployments CloudVision will automatically deploy certificates on the devices. + In case of AutoVPN + the certificates must be deployed manually to all devices. + + For LAB environments this can be + disabled, if there are no certificates available. + This should NOT be disabled for a WAN network + connected to the internet, since it will leave the STUN service exposed with no authentication. + wan_stun_dtls_profile_name: + Name of the SSL profile used for DTLS on WAN STUN connections. + When using automatic ceritficate + deployment via CloudVision this name must be the same on all WAN routers. + wan_virtual_topologies: + Configure Virtual Topologies for CV Pathfinder and AutoVPN. + Auto create a control plane + profile/policy/application and enforce it being first in the default VRF. + + Subclass of AvdModel. + zscaler_endpoints: + PREVIEW: These keys are in preview mode. + + Special data model used for testing the WAN internet-exit + integration with Zscaler. + The model is supposed to be autofilled per-device by `eos_designs`. + Manually setting this model will take precedence and prevent `eos_designs` from trying to contact + CloudVision. + This can be useful for offline testing or if CloudVision is not available or not + configured for Zscaler integration. + + Subclass of AvdModel. + _custom_data: _custom_data + _custom_structured_configurations: _custom_structured_configurations + _dynamic_keys: Dynamic keys + + """ 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 754b4e571e3..b241f60331a 100644 --- a/python-avd/pyavd/_eos_designs/schema/eos_designs.schema.yml +++ b/python-avd/pyavd/_eos_designs/schema/eos_designs.schema.yml @@ -6738,6 +6738,7 @@ $defs: ' enabled: type: bool + default: true mtu: type: int convert_types: @@ -7844,6 +7845,7 @@ $defs: documentation_options: table: node-type-uplink-configuration type: int + default: 1 convert_types: - str description: 'Number of parallel links towards uplink switches. @@ -10110,7 +10112,7 @@ $defs: Overrides `[].evpn_l2_multi_domain` and `[].vrfs[].evpn_l2_multi_domain`. - Not supported in conjuction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: + Not supported in conjunction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`. ' diff --git a/python-avd/pyavd/_eos_designs/schema/schema_fragments/defs_network_services.schema.yml b/python-avd/pyavd/_eos_designs/schema/schema_fragments/defs_network_services.schema.yml index 708d07ba2cd..8bf38f18c9a 100644 --- a/python-avd/pyavd/_eos_designs/schema/schema_fragments/defs_network_services.schema.yml +++ b/python-avd/pyavd/_eos_designs/schema/schema_fragments/defs_network_services.schema.yml @@ -709,6 +709,7 @@ $defs: "descriptions" has precedence over "description". enabled: type: bool + default: true mtu: type: int convert_types: 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 f84ea91cbb5..af03a895337 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/schema/schema_fragments/defs_svi_settings.schema.yml b/python-avd/pyavd/_eos_designs/schema/schema_fragments/defs_svi_settings.schema.yml index 44af7d3e6e1..579a1b2f1a1 100644 --- a/python-avd/pyavd/_eos_designs/schema/schema_fragments/defs_svi_settings.schema.yml +++ b/python-avd/pyavd/_eos_designs/schema/schema_fragments/defs_svi_settings.schema.yml @@ -308,4 +308,4 @@ $defs: description: | Explicitly extend SVI to remote EVPN domains. Overrides `[].evpn_l2_multi_domain` and `[].vrfs[].evpn_l2_multi_domain`. - Not supported in conjuction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`. + Not supported in conjunction with EVPN vlan aware bundles. i.e. `evpn_vlan_aware_bundles: true` or `[].evpn_vlan_bundle` or `[].vrfs[].svis[].evpn_vlan_bundle`. diff --git a/python-avd/pyavd/_eos_designs/shared_utils/__init__.py b/python-avd/pyavd/_eos_designs/shared_utils/__init__.py index ddc04d7295c..511e8eea589 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/__init__.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/__init__.py @@ -1,12 +1,10 @@ # Copyright (c) 2023-2024 Arista Networks, Inc. # Use of this source code is governed by the Apache License 2.0 # that can be found in the LICENSE file. +from pyavd._eos_designs.schema import EosDesigns from pyavd._schema.avdschema import AvdSchema -from .bgp_peer_groups import BgpPeerGroupsMixin -from .connected_endpoints_keys import ConnectedEndpointsKeysMixin from .cv_topology import CvTopology -from .descriptions import DescriptionsMixin from .filtered_tenants import FilteredTenantsMixin from .flow_tracking import FlowTrackingMixin from .inband_management import InbandManagementMixin @@ -17,22 +15,19 @@ from .mgmt import MgmtMixin from .misc import MiscMixin from .mlag import MlagMixin +from .node_config import NodeConfigMixin from .node_type import NodeTypeMixin from .node_type_keys import NodeTypeKeysMixin from .overlay import OverlayMixin from .platform import PlatformMixin from .ptp import PtpMixin from .routing import RoutingMixin -from .switch_data import SwitchDataMixin from .underlay import UnderlayMixin from .utils import UtilsMixin from .wan import WanMixin class SharedUtils( - BgpPeerGroupsMixin, - ConnectedEndpointsKeysMixin, - DescriptionsMixin, FilteredTenantsMixin, InbandManagementMixin, InterfaceDescriptionsMixin, @@ -43,13 +38,13 @@ class SharedUtils( MgmtMixin, MlagMixin, MiscMixin, + NodeConfigMixin, NodeTypeMixin, NodeTypeKeysMixin, OverlayMixin, PlatformMixin, PtpMixin, WanMixin, - SwitchDataMixin, RoutingMixin, UnderlayMixin, UtilsMixin, @@ -69,7 +64,8 @@ class SharedUtils( The class cannot be overridden. """ - def __init__(self, hostvars: dict, templar: object, schema: AvdSchema) -> None: + def __init__(self, hostvars: dict, inputs: EosDesigns, templar: object, schema: AvdSchema) -> None: self.hostvars = hostvars + self.inputs = inputs self.templar = templar self.schema = schema diff --git a/python-avd/pyavd/_eos_designs/shared_utils/bgp_peer_groups.py b/python-avd/pyavd/_eos_designs/shared_utils/bgp_peer_groups.py deleted file mode 100644 index 9689ed0f038..00000000000 --- a/python-avd/pyavd/_eos_designs/shared_utils/bgp_peer_groups.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright (c) 2023-2024 Arista Networks, Inc. -# Use of this source code is governed by the Apache License 2.0 -# that can be found in the LICENSE file. -from __future__ import annotations - -from functools import cached_property -from typing import TYPE_CHECKING - -from pyavd._utils import get - -if TYPE_CHECKING: - from . import SharedUtils - - -class BgpPeerGroupsMixin: - """ - Mixin Class providing a subset of SharedUtils. - - Class should only be used as Mixin to the SharedUtils class. - Using type-hint on self to get proper type-hints on attributes across all Mixins. - """ - - @cached_property - def bgp_peer_groups(self: SharedUtils) -> dict | None: - """ - Get bgp_peer_groups configurations or fallback to defaults. - - Supporting legacy uppercase keys as well. - """ - if not self.underlay_router: - return None - - default_bgp_peer_groups = [ - # key, default_name, default_bfd - # Default BFD is set to None when not True, to avoid generating config for disabling BFD - ("ipv4_underlay_peers", "IPv4-UNDERLAY-PEERS", None), - ("mlag_ipv4_underlay_peer", "MLAG-IPv4-UNDERLAY-PEER", None), - ("evpn_overlay_peers", "EVPN-OVERLAY-PEERS", True), - ("evpn_overlay_core", "EVPN-OVERLAY-CORE", True), - ("mpls_overlay_peers", "MPLS-OVERLAY-PEERS", True), - ("rr_overlay_peers", "RR-OVERLAY-PEERS", True), - ("ipvpn_gateway_peers", "IPVPN-GATEWAY-PEERS", True), - ("wan_overlay_peers", "WAN-OVERLAY-PEERS", True), - ("wan_rr_overlay_peers", "WAN-RR-OVERLAY-PEERS", True), - ] - - bgp_peer_groups = {} - for key, default_name, default_bfd in default_bgp_peer_groups: - bgp_peer_groups[key] = { - "name": get(self.hostvars, f"bgp_peer_groups.{key}.name", default=default_name), - "password": get(self.hostvars, f"bgp_peer_groups.{key}.password"), - "bfd": get(self.hostvars, f"bgp_peer_groups.{key}.bfd", default=default_bfd), - "structured_config": get(self.hostvars, f"bgp_peer_groups.{key}.structured_config"), - } - - if key == "wan_overlay_peers" and get(self.hostvars, f"bgp_peer_groups.{key}") is not None: - bgp_peer_groups[key]["listen_range_prefixes"] = get(self.hostvars, f"bgp_peer_groups.{key}.listen_range_prefixes", required=True) - - if key in ["wan_overlay_peers", "wan_rr_overlay_peers"]: - # For WAN peerings, set the TTL for maximum hops and use default timers for BFD - bgp_peer_groups[key]["ttl_maximum_hops"] = get(self.hostvars, f"bgp_peer_groups.{key}.ttl_maximum_hops", default=1) - - if get(self.hostvars, f"bgp_peer_groups.{key}.bfd", default=default_bfd): - bgp_peer_groups[key]["bfd_timers"] = get( - self.hostvars, - f"bgp_peer_groups.{key}.bfd_timers", - default={"interval": 1000, "min_rx": 1000, "multiplier": 10}, - ) - - return bgp_peer_groups diff --git a/python-avd/pyavd/_eos_designs/shared_utils/connected_endpoints_keys.py b/python-avd/pyavd/_eos_designs/shared_utils/connected_endpoints_keys.py deleted file mode 100644 index f6b9ada56be..00000000000 --- a/python-avd/pyavd/_eos_designs/shared_utils/connected_endpoints_keys.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) 2023-2024 Arista Networks, Inc. -# Use of this source code is governed by the Apache License 2.0 -# that can be found in the LICENSE file. -from __future__ import annotations - -from functools import cached_property -from typing import TYPE_CHECKING - -from pyavd._utils import get - -if TYPE_CHECKING: - from . import SharedUtils - - -class ConnectedEndpointsKeysMixin: - """ - Mixin Class providing a subset of SharedUtils. - - Class should only be used as Mixin to the SharedUtils class. - Using type-hint on self to get proper type-hints on attributes across all Mixins. - """ - - @cached_property - def connected_endpoints_keys(self: SharedUtils) -> list: - """ - Return connected_endpoints_keys filtered for invalid entries and unused keys. - - NOTE: This method is called _before_ any schema validation, since we need to resolve connected_endpoints_keys dynamically - """ - connected_endpoints_keys = [] - # Reading default value from schema - default_connected_endpoint_keys = self.schema.get_default_value(["connected_endpoints_keys"]) - connected_endpoints_keys = get(self.hostvars, "connected_endpoints_keys", default=default_connected_endpoint_keys) - return [entry for entry in connected_endpoints_keys if entry.get("key") is not None and self.hostvars.get(entry["key"]) is not None] diff --git a/python-avd/pyavd/_eos_designs/shared_utils/cv_topology.py b/python-avd/pyavd/_eos_designs/shared_utils/cv_topology.py index 9d89ae80744..bbd00ed22cb 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/cv_topology.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/cv_topology.py @@ -6,10 +6,12 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import get, get_item +from pyavd._errors import AristaAvdInvalidInputsError from pyavd.j2filters import range_expand if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + from . import SharedUtils @@ -22,7 +24,7 @@ class CvTopology: """ @cached_property - def cv_topology(self: SharedUtils) -> dict | None: + def cv_topology(self: SharedUtils) -> EosDesigns.CvTopologyItem | None: """ Returns the cv_topology for this device. @@ -38,22 +40,23 @@ def cv_topology(self: SharedUtils) -> dict | None: ]. } """ - if get(self.hostvars, "use_cv_topology") is not True: + if not self.inputs.use_cv_topology: return None - cv_topology = get( - self.hostvars, - "cv_topology", - required=True, - custom_error_msg="Found 'use_cv_topology:true' so 'cv_topology' is required.", - ) + if not self.inputs.cv_topology: + msg = "Found 'use_cv_topology:true' so 'cv_topology' is required." + raise AristaAvdInvalidInputsError(msg) + + if self.hostname not in self.inputs.cv_topology: + # Ignoring missing data for this device in cv_topology. Historic behavior and needed for hybrid scenarios. + return None - return get_item(cv_topology, "hostname", self.hostname) + return self.inputs.cv_topology[self.hostname] @cached_property def cv_topology_platform(self: SharedUtils) -> str | None: if self.cv_topology is not None: - return self.cv_topology.get("platform") + return self.cv_topology.platform return None @cached_property @@ -62,10 +65,10 @@ def cv_topology_config(self: SharedUtils) -> dict: Returns dict with keys derived from cv topology (or empty dict). { - uplink_interfaces: - uplink_switches: - uplink_switch_interfaces: - mlag_interfaces: + uplink_interfaces: list[str] + uplink_switches: list[str] + uplink_switch_interfaces: list[str] + mlag_interfaces: list[str] mlag_peer: mgmt_interface: } @@ -73,41 +76,34 @@ def cv_topology_config(self: SharedUtils) -> dict: if self.cv_topology is None: return {} - cv_interfaces = get(self.cv_topology, "interfaces", default=[]) - default_uplink_interfaces = range_expand( - get( - self.default_interfaces, - "uplink_interfaces", - required=True, - custom_error_msg="Found 'use_cv_topology:true' so 'default_interfaces.[].uplink_interfaces' is required.", - ), - ) + cv_interfaces = self.cv_topology.interfaces + + if not self.default_interfaces.uplink_interfaces: + msg = "Found 'use_cv_topology:true' so 'default_interfaces.[].uplink_interfaces' is required." + raise AristaAvdInvalidInputsError(msg) + config = {} - for uplink_interface in default_uplink_interfaces: - if cv_interface := get_item(cv_interfaces, "name", uplink_interface): - config.setdefault("uplink_interfaces", []).append(cv_interface["name"]) - config.setdefault("uplink_switches", []).append(cv_interface["neighbor"]) - config.setdefault("uplink_switch_interfaces", []).append(cv_interface["neighbor_interface"]) + for uplink_interface in range_expand(self.default_interfaces.uplink_interfaces): + if cv_interface := cv_interfaces.get(uplink_interface): + config.setdefault("uplink_interfaces", []).append(cv_interface.name) + config.setdefault("uplink_switches", []).append(cv_interface.neighbor) + config.setdefault("uplink_switch_interfaces", []).append(cv_interface.neighbor_interface) if not self.mlag: return config - default_mlag_interfaces = range_expand( - get( - self.default_interfaces, - "mlag_interfaces", - required=True, - custom_error_msg="Found 'use_cv_topology:true' so 'default_interfaces.[].mlag_interfaces' is required.", - ), - ) - for mlag_interface in default_mlag_interfaces: - if cv_interface := get_item(cv_interfaces, "name", mlag_interface): - config.setdefault("mlag_interfaces", []).append(cv_interface["name"]) + if not self.default_interfaces.mlag_interfaces: + msg = "Found 'use_cv_topology:true' so 'default_interfaces.[].mlag_interfaces' is required." + raise AristaAvdInvalidInputsError(msg) + + for mlag_interface in range_expand(self.default_interfaces.mlag_interfaces): + if cv_interface := cv_interfaces.get(mlag_interface, default=None): + config.setdefault("mlag_interfaces", []).append(cv_interface.name) # TODO: Set mlag_peer once we get a user-defined var for that. # TODO: config["mlag_peer"] = cv_interface["neighbor"] for cv_interface in cv_interfaces: - if cv_interface["name"].startswith("Management"): - config["mgmt_interface"] = cv_interface["name"] + if cv_interface.name.startswith("Management"): + config["mgmt_interface"] = cv_interface.name return config diff --git a/python-avd/pyavd/_eos_designs/shared_utils/descriptions.py b/python-avd/pyavd/_eos_designs/shared_utils/descriptions.py deleted file mode 100644 index 89d32af0353..00000000000 --- a/python-avd/pyavd/_eos_designs/shared_utils/descriptions.py +++ /dev/null @@ -1,121 +0,0 @@ -# Copyright (c) 2024 Arista Networks, Inc. -# Use of this source code is governed by the Apache License 2.0 -# that can be found in the LICENSE file. -from __future__ import annotations - -from functools import cached_property -from typing import TYPE_CHECKING - -from pyavd._utils import get - -if TYPE_CHECKING: - from . import SharedUtils - - -class DescriptionsMixin: - """ - Mixin Class providing a subset of SharedUtils. - - Class should only be used as Mixin to the SharedUtils class. - Using type-hint on self to get proper type-hints on attributes across all Mixins. - """ - - @cached_property - def default_network_ports_description(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["default_network_ports_description"]) - return get(self.hostvars, "default_network_ports_description", default=default_value) - - @cached_property - def default_network_ports_port_channel_description(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["default_network_ports_port_channel_description"]) - return get(self.hostvars, "default_network_ports_port_channel_description", default=default_value) - - @cached_property - def default_connected_endpoints_description(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["default_connected_endpoints_description"]) - return get(self.hostvars, "default_connected_endpoints_description", default=default_value) - - @cached_property - def default_connected_endpoints_port_channel_description(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["default_connected_endpoints_port_channel_description"]) - return get(self.hostvars, "default_connected_endpoints_port_channel_description", default=default_value) - - @cached_property - def mlag_member_description(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["mlag_member_description"]) - return get(self.hostvars, "mlag_member_description", default=default_value) - - @cached_property - def mlag_port_channel_description(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["mlag_port_channel_description"]) - return get(self.hostvars, "mlag_port_channel_description", default=default_value) - - @cached_property - def mlag_peer_svi_description(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["mlag_peer_svi_description"]) - return get(self.hostvars, "mlag_peer_svi_description", default=default_value) - - @cached_property - def mlag_peer_l3_svi_description(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["mlag_peer_l3_svi_description"]) - return get(self.hostvars, "mlag_peer_l3_svi_description", default=default_value) - - @cached_property - def mlag_peer_vlan_name(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["mlag_peer_vlan_name"]) - return get(self.hostvars, "mlag_peer_vlan_name", default=default_value) - - @cached_property - def mlag_peer_l3_vlan_name(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["mlag_peer_l3_vlan_name"]) - return get(self.hostvars, "mlag_peer_l3_vlan_name", default=default_value) - - @cached_property - def mlag_peer_l3_vrf_svi_description(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["mlag_peer_l3_vrf_svi_description"]) - return get(self.hostvars, "mlag_peer_l3_vrf_svi_description", default=default_value) - - @cached_property - def mlag_peer_l3_vrf_vlan_name(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["mlag_peer_l3_vrf_vlan_name"]) - return get(self.hostvars, "mlag_peer_l3_vrf_vlan_name", default=default_value) - - @cached_property - def mlag_bgp_peer_group_description(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["mlag_bgp_peer_group_description"]) - return get(self.hostvars, "mlag_bgp_peer_group_description", default=default_value) - - @cached_property - def mlag_bgp_peer_description(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["mlag_bgp_peer_description"]) - return get(self.hostvars, "mlag_bgp_peer_description", default=default_value) - - @cached_property - def overlay_bgp_peer_description(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["overlay_bgp_peer_description"]) - return get(self.hostvars, "overlay_bgp_peer_description", default=default_value) - - @cached_property - def default_underlay_p2p_ethernet_description(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["default_underlay_p2p_ethernet_description"]) - return get(self.hostvars, "default_underlay_p2p_ethernet_description", default=default_value) - - @cached_property - def default_underlay_p2p_port_channel_description(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["default_underlay_p2p_port_channel_description"]) - return get(self.hostvars, "default_underlay_p2p_port_channel_description", default=default_value) - - @cached_property - def underlay_l2_ethernet_description(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["underlay_l2_ethernet_description"]) - return get(self.hostvars, "underlay_l2_ethernet_description", default=default_value) - - @cached_property - def underlay_l2_port_channel_description(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["underlay_l2_port_channel_description"]) - return get(self.hostvars, "underlay_l2_port_channel_description", default=default_value) - - @cached_property - def default_vrf_diag_loopback_description(self: SharedUtils) -> str: - default_value = self.schema.get_default_value(["default_vrf_diag_loopback_description"]) - return get(self.hostvars, "default_vrf_diag_loopback_description", default=default_value) 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 d81c04eb870..bc36a8c3671 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/filtered_tenants.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/filtered_tenants.py @@ -6,8 +6,9 @@ from functools import cached_property from typing import TYPE_CHECKING +from pyavd._eos_designs.schema import EosDesigns from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError -from pyavd._utils import default, get, get_item, merge, unique +from pyavd._utils import default, unique from pyavd.j2filters import natural_sort, range_expand if TYPE_CHECKING: @@ -23,7 +24,7 @@ class FilteredTenantsMixin: """ @cached_property - def filtered_tenants(self: SharedUtils) -> list[dict]: + def filtered_tenants(self: SharedUtils) -> EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServices: """ Return sorted tenants list from all network_services_keys and filtered based on filter_tenants. @@ -31,101 +32,98 @@ def filtered_tenants(self: SharedUtils) -> list[dict]: All sub data models like vrfs and l2vlans are also converted and filtered. """ if not self.any_network_services: - return [] + return EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServices() - filtered_tenants = [] - filter_tenants = self.filter_tenants - for network_services_key in self.network_services_keys: - tenants = get(self.hostvars, network_services_key["name"]) - filtered_tenants.extend( - {**tenant, "l2vlans": self.filtered_l2vlans(tenant), "vrfs": self.filtered_vrfs(tenant)} - for tenant in tenants - if tenant["name"] in filter_tenants or "all" in filter_tenants - ) + filtered_tenants = EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServices() + filter_tenants = self.node_config.filter.tenants + for network_services_key in self.inputs._dynamic_keys.network_services: + for original_tenant in network_services_key.value: + if original_tenant.name not in filter_tenants and "all" not in filter_tenants: + continue + tenant = original_tenant._deepcopy() + tenant.l2vlans = self.filtered_l2vlans(tenant) + tenant.vrfs = self.filtered_vrfs(tenant) + filtered_tenants.append(tenant) - no_vrf_default = all(vrf["name"] != "default" for tenant in filtered_tenants for vrf in tenant["vrfs"]) + no_vrf_default = all("default" not in tenant.vrfs for tenant in filtered_tenants) if self.is_wan_router and no_vrf_default: filtered_tenants.append( - { - "name": "WAN_DEFAULT", - "vrfs": [ - { - "name": "default", - "vrf_id": 1, - "svis": [], - "l3_interfaces": [], - "bgp_peers": [], - "ipv6_static_routes": [], - "static_routes": [], - "loopbacks": [], - "additional_route_targets": [], - } - ], - "l2vlans": [], - }, + EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem( + name="WAN_DEFAULT", + vrfs=EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.Vrfs( + [ + EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem( + name="default", + vrf_id=1, + ) + ] + ), + ) ) elif self.is_wan_router: # It is enough to check only the first occurrence of default VRF as some other piece of code # checks that if the VRF is in multiple tenants, the configuration is consistent. for tenant in filtered_tenants: - if (vrf_default := get_item(tenant["vrfs"], "name", "default")) is None: + if "default" not in tenant.vrfs: continue - if "evpn" in vrf_default.get("address_families", ["evpn"]) and self.underlay_filter_peer_as: + if "evpn" not in tenant.vrfs["default"].address_families: msg = "WAN configuration requires EVPN to be enabled for VRF 'default'. Got 'address_families: {vrf_default['address_families']}." - raise AristaAvdError( - msg, - ) + raise AristaAvdError(msg) + if self.inputs.underlay_filter_peer_as: + msg = "WAN configuration is not compatible with 'underlay_filter_peer_as'" + raise AristaAvdError break - return natural_sort(filtered_tenants, "name") + return filtered_tenants._natural_sorted() - def filtered_l2vlans(self: SharedUtils, tenant: dict) -> list[dict]: + def filtered_l2vlans( + self: SharedUtils, tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem + ) -> EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.L2vlans: """ Return sorted and filtered l2vlan list from given tenant. Filtering based on l2vlan tags. """ - if not self.network_services_l2: - return [] + if not self.network_services_l2 or not tenant.l2vlans: + EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.L2vlans() - if "l2vlans" not in tenant: - return [] - - l2vlans: list[dict] = natural_sort(tenant["l2vlans"], "id") + filtered_l2vlans = tenant.l2vlans._filtered( + lambda l2vlan: self.is_accepted_vlan(l2vlan) and bool("all" in self.filter_tags or set(l2vlan.tags).intersection(self.filter_tags)) + ) + # Set tenant on all l2vlans TODO: avoid this. + for l2vlan in filtered_l2vlans: + l2vlan._tenant = tenant.name - if tenant_evpn_vlan_bundle := get(tenant, "evpn_vlan_bundle"): - for l2vlan in l2vlans: - l2vlan["evpn_vlan_bundle"] = get(l2vlan, "evpn_vlan_bundle", default=tenant_evpn_vlan_bundle) + if tenant.evpn_vlan_bundle: + for l2vlan in filtered_l2vlans: + l2vlan.evpn_vlan_bundle = l2vlan.evpn_vlan_bundle or tenant.evpn_vlan_bundle - return [ - # Copy and set tenant key on all l2vlans - {**l2vlan, "tenant": tenant["name"]} - for l2vlan in l2vlans - if self.is_accepted_vlan(l2vlan) and ("all" in self.filter_tags or set(l2vlan.get("tags", ["all"])).intersection(self.filter_tags)) - ] + return filtered_l2vlans._natural_sorted(sort_key="id") - def is_accepted_vlan(self: SharedUtils, vlan: dict) -> bool: + def is_accepted_vlan( + self: SharedUtils, + vlan: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.L2vlansItem + | EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem, + ) -> bool: """ Check if vlan is in accepted_vlans list. If filter.only_vlans_in_use is True also check if vlan id or trunk group is assigned to connected endpoint. """ - vlan_id = int(vlan["id"]) - - if vlan_id not in self.accepted_vlans: + if vlan.id not in self.accepted_vlans: return False - if not self.filter_only_vlans_in_use: + if not self.node_config.filter.only_vlans_in_use: # No further filtering return True - if vlan_id in self.endpoint_vlans: + if vlan.id in self.endpoint_vlans: return True # Picking this up from facts so this would fail if accessed when shared_utils is run before facts # TODO: see if this can be optimized endpoint_trunk_groups = set(self.get_switch_fact("endpoint_trunk_groups", required=False) or []) - return self.enable_trunk_groups and vlan.get("trunk_groups") and endpoint_trunk_groups.intersection(vlan["trunk_groups"]) + return bool(self.inputs.enable_trunk_groups and vlan.trunk_groups and endpoint_trunk_groups.intersection(vlan.trunk_groups)) @cached_property def accepted_vlans(self: SharedUtils) -> list[int]: @@ -154,7 +152,7 @@ def accepted_vlans(self: SharedUtils) -> list[int]: return accepted_vlans - def is_accepted_vrf(self: SharedUtils, vrf: dict) -> bool: + def is_accepted_vrf(self: SharedUtils, vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem) -> bool: """ Returns True if. @@ -164,11 +162,11 @@ def is_accepted_vrf(self: SharedUtils, vrf: dict) -> bool: - filter.not_vrfs == [] OR VRF is NOT in filter.deny_vrfs """ - return ("all" in self.filter_allow_vrfs or vrf["name"] in self.filter_allow_vrfs) and ( - not self.filter_deny_vrfs or vrf["name"] not in self.filter_deny_vrfs + return ("all" in self.node_config.filter.allow_vrfs or vrf.name in self.node_config.filter.allow_vrfs) and ( + not self.node_config.filter.deny_vrfs or vrf.name not in self.node_config.filter.deny_vrfs ) - def is_forced_vrf(self: SharedUtils, vrf: dict) -> bool: + def is_forced_vrf(self: SharedUtils, vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem, tenant_name: str) -> bool: """ Returns True if the given VRF name should be configured even without any loopbacks or SVIs etc. @@ -177,115 +175,86 @@ def is_forced_vrf(self: SharedUtils, vrf: dict) -> bool: - 'always_include_vrfs_in_tenants' is set to ['all'] - This device is using 'p2p-vrfs' as uplink type and the VRF present on the uplink switch. """ - if "all" in self.always_include_vrfs_in_tenants or vrf["tenant"] in self.always_include_vrfs_in_tenants: + if "all" in self.node_config.filter.always_include_vrfs_in_tenants or tenant_name in self.node_config.filter.always_include_vrfs_in_tenants: return True - return vrf["name"] in (self.get_switch_fact("uplink_switch_vrfs", required=False) or []) + return vrf.name in (self.get_switch_fact("uplink_switch_vrfs", required=False) or []) - def filtered_vrfs(self: SharedUtils, tenant: dict) -> list[dict]: + def filtered_vrfs( + self: SharedUtils, tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem + ) -> EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.Vrfs: """ Return sorted and filtered vrf list from given tenant. Filtering based on svi tags, l3interfaces, loopbacks or self.is_forced_vrf() check. Keys of VRF data model will be converted to lists. """ - filtered_vrfs = [] + filtered_vrfs = EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.Vrfs() - vrfs: list[dict] = natural_sort(tenant.get("vrfs", []), "name") - for original_vrf in vrfs: - if not self.is_accepted_vrf(original_vrf): + for vrf in tenant.vrfs._natural_sorted(): + if not self.is_accepted_vrf(vrf): continue - # Copying original_vrf and setting "tenant" for use by child objects like SVIs - vrf = {**original_vrf, "tenant": tenant["name"]} + # Copying original_vrf + vrf._tenant = tenant.name - bgp_peers = natural_sort(vrf.get("bgp_peers"), "ip_address") - vrf["bgp_peers"] = [bgp_peer for bgp_peer in bgp_peers if self.hostname in bgp_peer.get("nodes", [])] - vrf["static_routes"] = [route for route in get(vrf, "static_routes", default=[]) if self.hostname in get(route, "nodes", default=[self.hostname])] - vrf["ipv6_static_routes"] = [ - route for route in get(vrf, "ipv6_static_routes", default=[]) if self.hostname in get(route, "nodes", default=[self.hostname]) - ] - vrf["svis"] = self.filtered_svis(vrf) - vrf["l3_interfaces"] = [ - l3_interface - for l3_interface in get(vrf, "l3_interfaces", default=[]) - if ( - self.hostname in get(l3_interface, "nodes", default=[]) - and l3_interface.get("ip_addresses") is not None - and l3_interface.get("interfaces") is not None - ) - ] - vrf["loopbacks"] = [loopback for loopback in get(vrf, "loopbacks", default=[]) if self.hostname == get(loopback, "node")] + vrf.bgp_peers = vrf.bgp_peers._filtered(lambda bgp_peer: self.hostname in bgp_peer.nodes)._natural_sorted(sort_key="ip_address") + vrf.static_routes = vrf.static_routes._filtered(lambda route: not route.nodes or self.hostname in route.nodes) + vrf.ipv6_static_routes = vrf.ipv6_static_routes._filtered(lambda route: not route.nodes or self.hostname in route.nodes) + vrf.svis = self.filtered_svis(vrf) + vrf.l3_interfaces = vrf.l3_interfaces._filtered( + lambda l3_interface: bool(self.hostname in l3_interface.nodes and l3_interface.ip_addresses and l3_interface.interfaces) + ) + vrf.loopbacks = vrf.loopbacks._filtered(lambda loopback: loopback.node == self.hostname) if self.vtep is True: - evpn_l3_multicast_enabled = default(get(vrf, "evpn_l3_multicast.enabled"), get(tenant, "evpn_l3_multicast.enabled")) + evpn_l3_multicast_enabled = default(vrf.evpn_l3_multicast.enabled, tenant.evpn_l3_multicast.enabled) + # TODO: Consider if all this should be moved out of filtered_vrfs. if self.evpn_multicast: - vrf["_evpn_l3_multicast_enabled"] = evpn_l3_multicast_enabled - vrf["_evpn_l3_multicast_group_ip"] = get(vrf, "evpn_l3_multicast.evpn_underlay_l3_multicast_group") + vrf._evpn_l3_multicast_enabled = evpn_l3_multicast_enabled + vrf._evpn_l3_multicast_group_ip = vrf.evpn_l3_multicast.evpn_underlay_l3_multicast_group rps = [] - for rp_entry in default(get(vrf, "pim_rp_addresses"), get(tenant, "pim_rp_addresses"), []): - if self.hostname in get(rp_entry, "nodes", default=[self.hostname]): - for rp_ip in get( - rp_entry, - "rps", - required=True, - custom_error_msg=f"'pim_rp_addresses.rps' under VRF '{vrf['name']}' in Tenant '{tenant['name']}' is required.", - ): + for rp_entry in vrf.pim_rp_addresses or tenant.pim_rp_addresses: + if not rp_entry.nodes or self.hostname in rp_entry.nodes: + if not rp_entry.rps: + # TODO: Evaluate if schema should just have required for this key. + msg = f"'pim_rp_addresses.rps' under VRF '{vrf.name}' in Tenant '{tenant.name}' is required." + raise AristaAvdInvalidInputsError(msg) + for rp_ip in rp_entry.rps: rp_address = {"address": rp_ip} - if (rp_groups := get(rp_entry, "groups")) is not None: - if (acl := rp_entry.get("access_list_name")) is not None: - rp_address["access_lists"] = [acl] + if rp_entry.groups: + if rp_entry.access_list_name: + rp_address["access_lists"] = [rp_entry.access_list_name] else: - rp_address["groups"] = rp_groups + rp_address["groups"] = rp_entry.groups._as_list() rps.append(rp_address) if rps: - vrf["_pim_rp_addresses"] = rps - - for evpn_peg in default(get(vrf, "evpn_l3_multicast.evpn_peg"), get(tenant, "evpn_l3_multicast.evpn_peg"), []): - if self.hostname in evpn_peg.get("nodes", [self.hostname]) and rps: - vrf["_evpn_l3_multicast_evpn_peg_transit"] = evpn_peg.get("transit") - break - - vrf["additional_route_targets"] = [ - rt - for rt in get(vrf, "additional_route_targets", default=[]) - if ( - self.hostname in get(rt, "nodes", default=[self.hostname]) - and rt.get("address_family") is not None - and rt.get("route_target") is not None - and rt.get("type") in ["import", "export"] - ) - ] + vrf._pim_rp_addresses = rps - if vrf["svis"] or vrf["l3_interfaces"] or vrf["loopbacks"] or self.is_forced_vrf(vrf): + for evpn_peg in vrf.evpn_l3_multicast.evpn_peg or tenant.evpn_l3_multicast.evpn_peg: + if not evpn_peg.nodes or self.hostname in evpn_peg.nodes: + vrf._evpn_l3_multicast_evpn_peg_transit = evpn_peg.transit + break + + vrf.additional_route_targets = vrf.additional_route_targets._filtered( + lambda rt: bool((not rt.nodes or self.hostname in rt.nodes) and rt.address_family and rt.route_target and rt.type in ["import", "export"]) + ) + + if vrf.svis or vrf.l3_interfaces or vrf.loopbacks or self.is_forced_vrf(vrf, tenant.name): filtered_vrfs.append(vrf) - if tenant_evpn_vlan_bundle := get(tenant, "evpn_vlan_bundle"): - for svi in vrf["svis"]: - svi["evpn_vlan_bundle"] = get(svi, "evpn_vlan_bundle", default=tenant_evpn_vlan_bundle) + if tenant_evpn_vlan_bundle := tenant.evpn_vlan_bundle: + for svi in vrf.svis: + svi.evpn_vlan_bundle = svi.evpn_vlan_bundle or tenant_evpn_vlan_bundle return filtered_vrfs - @cached_property - def svi_profiles(self: SharedUtils) -> list[dict]: - """ - Return list of svi_profiles. - - The key "nodes" is filtered to only contain one item with the relevant dict from "nodes" or {} - """ - svi_profiles = get(self.hostvars, "svi_profiles", default=[]) - return [ - { - **svi_profile, - "nodes": [get_item(svi_profile.get("nodes", []), "node", self.hostname, default={})], - } - for svi_profile in svi_profiles - ] - - def get_merged_svi_config(self: SharedUtils, svi: dict) -> list[dict]: + def get_merged_svi_config( + self: SharedUtils, svi: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem + ) -> EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem: """ Return structured config for one svi after inheritance. @@ -299,40 +268,39 @@ def get_merged_svi_config(self: SharedUtils, svi: dict) -> list[dict]: Then svi is updated with the result of merging svi_node_cfg over svi_cfg svi_node_cfg > svi_cfg --> svi """ - svi_profile = {"nodes": [{}]} - svi_parent_profile = {"nodes": [{}]} - - filtered_svi = { - **svi, - "nodes": [get_item(svi.get("nodes", []), "node", self.hostname, default={})], - } - - if (svi_profile_name := filtered_svi.get("profile")) is not None: - msg = f"Profile '{svi_profile_name}' applied under SVI '{filtered_svi['name']}' does not exist in `svi_profiles`." - svi_profile = get_item(self.svi_profiles, "profile", svi_profile_name, required=True, custom_error_msg=msg) - - if (svi_parent_profile_name := svi_profile.get("parent_profile")) is not None: - msg = f"Profile '{svi_parent_profile_name}' applied under SVI Profile '{svi_profile_name}' does not exist in `svi_profiles`." - svi_parent_profile = get_item(self.svi_profiles, "profile", svi_parent_profile_name, required=True, custom_error_msg=msg) - - # deepmerge all levels of config - later vars override previous. - # Using destructive_merge=False to avoid having references to profiles and other data. - # Instead it will be doing deep copies inside merge. - merged_svi: dict = merge( - svi_parent_profile, - svi_profile, - filtered_svi, - svi_parent_profile["nodes"][0], - svi_profile["nodes"][0], - filtered_svi["nodes"][0], - list_merge="replace", - destructive_merge=False, - ) - merged_svi.pop("profile", None) - merged_svi.pop("parent_profile", None) + if svi.profile: + if svi.profile not in self.inputs.svi_profiles: + msg = f"Profile '{svi.profile}' applied under SVI '{svi.name}' does not exist in `svi_profiles`." + raise AristaAvdInvalidInputsError(msg) + svi_profile = self.inputs.svi_profiles[svi.profile]._deepcopy() + + if svi_profile.parent_profile: + if svi_profile.parent_profile not in self.inputs.svi_profiles: + msg = f"Profile '{svi_profile.parent_profile}' applied under SVI Profile '{svi_profile.profile}' does not exist in `svi_profiles`." + raise AristaAvdInvalidInputsError(msg) + + # Inherit from the parent profile + svi_profile._deepinherit(self.inputs.svi_profiles[svi_profile.parent_profile]) + + # Inherit from the profile + merged_svi = svi._deepinherited( + svi_profile._cast_as(EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem, ignore_extra_keys=True) + ) + else: + merged_svi = svi + + # Merge node specific SVI over the general SVI data. + if self.hostname in merged_svi.nodes: + node_specific_svi = merged_svi.nodes[self.hostname]._cast_as( + EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem, ignore_extra_keys=True + ) + merged_svi._deepmerge(node_specific_svi, list_merge="replace") + return merged_svi - def filtered_svis(self: SharedUtils, vrf: dict) -> list[dict]: + def filtered_svis( + self: SharedUtils, vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem + ) -> EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.Svis: """ Return sorted and filtered svi list from given tenant vrf. @@ -340,22 +308,21 @@ def filtered_svis(self: SharedUtils, vrf: dict) -> list[dict]: filtered that on tags and trunk_groups. """ if not (self.network_services_l2 or self.network_services_l2_as_subint): - return [] + return EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.Svis() - svis: list[dict] = natural_sort(vrf.get("svis", []), "id") - svis = [svi for svi in svis if self.is_accepted_vlan(svi)] + svis = vrf.svis._filtered(self.is_accepted_vlan) # Handle svi_profile inheritance - svis = [self.get_merged_svi_config(svi) for svi in svis] + svis = EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.Svis([self.get_merged_svi_config(svi) for svi in svis]) # Perform filtering on tags after merge of profiles, to support tags being set inside profiles. - svis = [svi for svi in svis if "all" in self.filter_tags or set(svi.get("tags", ["all"])).intersection(self.filter_tags)] + svis = svis._filtered(lambda svi: "all" in self.filter_tags or bool(set(svi.tags).intersection(self.filter_tags))) # Set tenant key on all SVIs for svi in svis: - svi.update({"tenant": vrf["tenant"]}) + svi._tenant = vrf._tenant - return svis + return svis._natural_sorted(sort_key="id") @cached_property def endpoint_vlans(self: SharedUtils) -> list: @@ -365,25 +332,23 @@ def endpoint_vlans(self: SharedUtils) -> list: return [int(vlan_id) for vlan_id in range_expand(endpoint_vlans)] @staticmethod - def get_vrf_id(vrf: dict, required: bool = True) -> int | None: - vrf_id = default(vrf.get("vrf_id"), vrf.get("vrf_vni")) - if vrf_id is None: - if required: - msg = f"'vrf_id' or 'vrf_vni' for VRF '{vrf['name']} must be set." - raise AristaAvdInvalidInputsError(msg) - return None - return int(vrf_id) + 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." + raise AristaAvdInvalidInputsError(msg) + return vrf_id @staticmethod - def get_vrf_vni(vrf: dict) -> int: - vrf_vni = default(vrf.get("vrf_vni"), vrf.get("vrf_id")) + 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 int(vrf_vni) + return vrf_vni @cached_property - def vrfs(self: SharedUtils) -> list: + def vrfs(self: SharedUtils) -> list[str]: """ Return the list of vrfs to be defined on this switch. @@ -392,15 +357,14 @@ def vrfs(self: SharedUtils) -> list: if not self.network_services_l3: return [] - vrfs = set() - for tenant in self.filtered_tenants: - for vrf in tenant["vrfs"]: - vrfs.add(vrf["name"]) - - return natural_sort(vrfs) + return natural_sort({vrf.name for tenant in self.filtered_tenants for vrf in tenant.vrfs}) @staticmethod - def get_additional_svi_config(svi_config: dict, svi: dict, vrf: dict) -> None: + def get_additional_svi_config( + svi_config: dict, + svi: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem, + vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem, + ) -> None: """ Adding IP helpers and OSPF for SVIs via a common function. @@ -408,31 +372,31 @@ def get_additional_svi_config(svi_config: dict, svi: dict, vrf: dict) -> None: The given svi_config is updated in-place. """ - svi_ip_helpers: list[dict] = default(svi.get("ip_helpers"), vrf.get("ip_helpers"), []) + svi_ip_helpers = svi.ip_helpers or vrf.ip_helpers if svi_ip_helpers: svi_config["ip_helpers"] = [ - {"ip_helper": svi_ip_helper["ip_helper"], "source_interface": svi_ip_helper.get("source_interface"), "vrf": svi_ip_helper.get("source_vrf")} + {"ip_helper": svi_ip_helper.ip_helper, "source_interface": svi_ip_helper.source_interface, "vrf": svi_ip_helper.source_vrf} for svi_ip_helper in svi_ip_helpers ] - if get(svi, "ospf.enabled") is True and get(vrf, "ospf.enabled") is True: + if svi.ospf.enabled and vrf.ospf.enabled: svi_config.update( { - "ospf_area": svi["ospf"].get("area", "0.0.0.0"), # noqa: S104 - "ospf_network_point_to_point": svi["ospf"].get("point_to_point", False), - "ospf_cost": svi["ospf"].get("cost"), + "ospf_area": svi.ospf.area, + "ospf_network_point_to_point": svi.ospf.point_to_point, + "ospf_cost": svi.ospf.cost, }, ) - ospf_authentication = svi["ospf"].get("authentication") - if ospf_authentication == "simple" and (ospf_simple_auth_key := svi["ospf"].get("simple_auth_key")) is not None: + ospf_authentication = svi.ospf.authentication + if ospf_authentication == "simple" and (ospf_simple_auth_key := svi.ospf.simple_auth_key) is not None: svi_config.update({"ospf_authentication": ospf_authentication, "ospf_authentication_key": ospf_simple_auth_key}) - elif ospf_authentication == "message-digest" and (ospf_message_digest_keys := svi["ospf"].get("message_digest_keys")) is not None: + elif ospf_authentication == "message-digest" and (ospf_message_digest_keys := svi.ospf.message_digest_keys) is not None: ospf_keys = [] for ospf_key in ospf_message_digest_keys: - if not ("id" in ospf_key and "key" in ospf_key): + if not (ospf_key.id and ospf_key.key): continue - ospf_keys.append({"id": ospf_key["id"], "hash_algorithm": ospf_key.get("hash_algorithm", "sha512"), "key": ospf_key["key"]}) + ospf_keys.append({"id": ospf_key.id, "hash_algorithm": ospf_key.hash_algorithm, "key": ospf_key.key}) if ospf_keys: svi_config.update({"ospf_authentication": ospf_authentication, "ospf_message_digest_keys": ospf_keys}) @@ -446,9 +410,9 @@ def bgp_in_network_services(self: SharedUtils) -> bool: if not self.network_services_l3: return False - return any(self.bgp_enabled_for_vrf(vrf) for tenant in self.filtered_tenants for vrf in tenant["vrfs"]) + return any(self.bgp_enabled_for_vrf(vrf) for tenant in self.filtered_tenants for vrf in tenant.vrfs) - def bgp_enabled_for_vrf(self: SharedUtils, vrf: dict) -> bool: + def bgp_enabled_for_vrf(self: SharedUtils, vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem) -> bool: """ True if the given VRF should be included under Router BGP. @@ -460,14 +424,14 @@ def bgp_enabled_for_vrf(self: SharedUtils, vrf: dict) -> bool: - If any BGP peers are configured we will configure BGP for it. - If uplink type is p2p_vrfs and the vrf is included in uplink VRFs. """ - if (bgp_enabled := get(vrf, "bgp.enabled")) is not None: - return bgp_enabled + if vrf.bgp.enabled is not None: + return vrf.bgp.enabled - vrf_address_families = [af for af in vrf.get("address_families", ["evpn"]) if af in self.overlay_address_families] + vrf_address_families = [af for af in vrf.address_families if af in self.overlay_address_families] return any( [ vrf_address_families, - vrf["bgp_peers"], - (self.uplink_type == "p2p-vrfs" and vrf["name"] in (self.get_switch_fact("uplink_switch_vrfs", required=False) or [])), + vrf.bgp_peers, + (self.uplink_type == "p2p-vrfs" and vrf.name in (self.get_switch_fact("uplink_switch_vrfs", required=False) or [])), ] ) diff --git a/python-avd/pyavd/_eos_designs/shared_utils/flow_tracking.py b/python-avd/pyavd/_eos_designs/shared_utils/flow_tracking.py index b6b962068b1..aeb043eb602 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/flow_tracking.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/flow_tracking.py @@ -3,15 +3,28 @@ # that can be found in the LICENSE file. from __future__ import annotations -from collections import defaultdict from functools import cached_property from typing import TYPE_CHECKING, Literal -from pyavd._utils import get +from pyavd._eos_designs.schema import EosDesigns +from pyavd._utils import default if TYPE_CHECKING: from . import SharedUtils + FlowTracking = ( + EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem.FlowTracking + | EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.L3InterfacesItem.FlowTracking + | EosDesigns.CoreInterfaces.P2pLinksItem.FlowTracking + | EosDesigns.L3Edge.P2pLinksItem.FlowTracking + | EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem.WanHa.FlowTracking + | EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem.L3InterfacesItem.FlowTracking + | EosDesigns.FabricFlowTracking.MlagInterfaces + | EosDesigns.FabricFlowTracking.DpsInterfaces + | EosDesigns.FabricFlowTracking.Uplinks + | EosDesigns.FabricFlowTracking.Downlinks + ) + class FlowTrackingMixin: """ @@ -22,68 +35,41 @@ class FlowTrackingMixin: """ @cached_property - def flow_tracking_type(self: SharedUtils) -> str: - default_flow_tracker_type = get(self.node_type_key_data, "default_flow_tracker_type", "sampled") - return get(self.switch_data_combined, "flow_tracker_type", default=default_flow_tracker_type) - - @cached_property - def default_flow_tracker_name(self: SharedUtils) -> str: - return "FLOW-TRACKER" - - @cached_property - def fabric_flow_tracking(self: SharedUtils) -> defaultdict: - """Return fabric level flow tracking settings for all data models.""" - configured_values = get(self.hostvars, "fabric_flow_tracking", default={}) - - # By default, flow tracker is `hardware` type named `FLOW-TRACKER` - output_settings = defaultdict( - lambda: { - "enabled": None, - "name": self.default_flow_tracker_name, - }, - ) - - # By default, flow tracking is enabled only on DPS interfaces - output_settings["dps_interfaces"]["enabled"] = True + def flow_tracking_type(self: SharedUtils) -> Literal["sampled", "hardware"]: + default_flow_tracker_type = self.node_type_key_data.default_flow_tracker_type + return self.node_config.flow_tracker_type or default_flow_tracker_type - for data_model, settings in configured_values.items(): - tracker_enabled = settings.get("enabled") - tracker_name = settings.get("name") - - if tracker_enabled is not None: - output_settings[data_model]["enabled"] = tracker_enabled - - if tracker_name: - output_settings[data_model]["name"] = tracker_name - return output_settings - - def get_flow_tracker( - self: SharedUtils, - link_settings: dict | None, - data_model: Literal[ - "uplinks", - "downlinks", - "endpoints", - "l3_edge", - "core_interfaces", - "mlag_interfaces", - "l3_interfaces", - "dps_interfaces", - "direct_wan_ha_links", - ], - ) -> dict: + def get_flow_tracker(self: SharedUtils, flow_tracking: FlowTracking) -> dict[str, str] | None: """Return flow_tracking settings for a link, falling back to the fabric flow_tracking_settings if not defined.""" - link_tracker_enabled, link_tracker_name = None, None - if link_settings is not None: - link_tracker_enabled = get(link_settings, "flow_tracking.enabled") - link_tracker_name = get(link_settings, "flow_tracking.name") - - fabric_flow = self.fabric_flow_tracking[data_model] - - tracking_enabled = link_tracker_enabled if link_tracker_enabled is not None else fabric_flow["enabled"] - if not tracking_enabled: + match flow_tracking: + case EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem.FlowTracking(): + enabled: bool = default(flow_tracking.enabled, self.inputs.fabric_flow_tracking.endpoints.enabled) + name: str = default(flow_tracking.name, self.inputs.fabric_flow_tracking.endpoints.name) + case EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.L3InterfacesItem.FlowTracking(): + enabled: bool = default(flow_tracking.enabled, self.inputs.fabric_flow_tracking.l3_interfaces.enabled) + name: str = default(flow_tracking.name, self.inputs.fabric_flow_tracking.l3_interfaces.name) + case EosDesigns.CoreInterfaces.P2pLinksItem.FlowTracking(): + enabled: bool = default(flow_tracking.enabled, self.inputs.fabric_flow_tracking.core_interfaces.enabled) + name: str = default(flow_tracking.name, self.inputs.fabric_flow_tracking.core_interfaces.name) + case EosDesigns.L3Edge.P2pLinksItem.FlowTracking(): + enabled: bool = default(flow_tracking.enabled, self.inputs.fabric_flow_tracking.l3_edge.enabled) + name: str = default(flow_tracking.name, self.inputs.fabric_flow_tracking.l3_edge.name) + case EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem.WanHa.FlowTracking(): + enabled: bool = default(flow_tracking.enabled, self.inputs.fabric_flow_tracking.direct_wan_ha_links.enabled) + name: str = default(flow_tracking.name, self.inputs.fabric_flow_tracking.direct_wan_ha_links.name) + case EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem.L3InterfacesItem.FlowTracking(): + enabled: bool = default(flow_tracking.enabled, self.inputs.fabric_flow_tracking.l3_interfaces.enabled) + name: str = default(flow_tracking.name, self.inputs.fabric_flow_tracking.l3_interfaces.name) + case ( + EosDesigns.FabricFlowTracking.MlagInterfaces() + | EosDesigns.FabricFlowTracking.DpsInterfaces() + | EosDesigns.FabricFlowTracking.Uplinks() + | EosDesigns.FabricFlowTracking.Downlinks() + ): + enabled: bool = flow_tracking.enabled + name: str = flow_tracking.name + + if not enabled: return None - tracker_name = link_tracker_name or fabric_flow["name"] - - return {self.flow_tracking_type: tracker_name} + return {self.flow_tracking_type: name} 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 47d52e207b3..fa2e7a86efc 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/inband_management.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/inband_management.py @@ -8,7 +8,7 @@ from typing import TYPE_CHECKING from pyavd._errors import AristaAvdInvalidInputsError -from pyavd._utils import default, get +from pyavd._utils import get from pyavd.j2filters import natural_sort if TYPE_CHECKING: @@ -25,50 +25,30 @@ class InbandManagementMixin: @cached_property def configure_inband_mgmt(self: SharedUtils) -> bool: - return self.uplink_type == "port-channel" and self.inband_mgmt_ip + return bool(self.uplink_type == "port-channel" and self.inband_mgmt_ip) @cached_property def configure_inband_mgmt_ipv6(self: SharedUtils) -> bool: - return self.uplink_type == "port-channel" and self.inband_mgmt_ipv6_address + return bool(self.uplink_type == "port-channel" and self.inband_mgmt_ipv6_address) @cached_property def configure_parent_for_inband_mgmt(self: SharedUtils) -> bool: - return self.configure_inband_mgmt and get(self.switch_data_combined, "inband_mgmt_ip") is None + return self.configure_inband_mgmt and not self.node_config.inband_mgmt_ip @cached_property def configure_parent_for_inband_mgmt_ipv6(self: SharedUtils) -> bool: - return self.configure_inband_mgmt_ipv6 and get(self.switch_data_combined, "inband_mgmt_ipv6_address") is None - - @cached_property - def inband_mgmt_subnet(self: SharedUtils) -> str | None: - return get(self.switch_data_combined, "inband_mgmt_subnet") - - @cached_property - def inband_mgmt_ipv6_subnet(self: SharedUtils) -> str | None: - return get(self.switch_data_combined, "inband_mgmt_ipv6_subnet") - - @cached_property - def inband_mgmt_vlan(self: SharedUtils) -> int: - return int(get(self.switch_data_combined, "inband_mgmt_vlan", default=4092)) - - @cached_property - def inband_mgmt_description(self: SharedUtils) -> str: - return get(self.switch_data_combined, "inband_mgmt_description", default="Inband Management") + return self.configure_inband_mgmt_ipv6 and not self.node_config.inband_mgmt_ipv6_address @cached_property def inband_mgmt_mtu(self: SharedUtils) -> int | None: - if not self.platform_settings_feature_support_per_interface_mtu: + if not self.platform_settings.feature_support.per_interface_mtu: return None - return get(self.switch_data_combined, "inband_mgmt_mtu", default=1500) - - @cached_property - def inband_mgmt_vlan_name(self: SharedUtils) -> str: - return get(self.switch_data_combined, "inband_mgmt_vlan_name", default="INBAND_MGMT") + return self.node_config.inband_mgmt_mtu @cached_property def inband_mgmt_vrf(self: SharedUtils) -> str | None: - if (inband_mgmt_vrf := get(self.switch_data_combined, "inband_mgmt_vrf")) != "default": + if (inband_mgmt_vrf := self.node_config.inband_mgmt_vrf) != "default": return inband_mgmt_vrf return None @@ -84,13 +64,16 @@ def inband_mgmt_gateway(self: SharedUtils) -> str | None: Otherwise return None """ - if self.inband_mgmt_ip is None: + if not self.inband_mgmt_ip: return None if not self.configure_parent_for_inband_mgmt: - return get(self.switch_data_combined, "inband_mgmt_gateway") + return self.node_config.inband_mgmt_gateway + + if not self.node_config.inband_mgmt_subnet: + return None - subnet = ip_network(self.inband_mgmt_subnet, strict=False) + subnet = ip_network(self.node_config.inband_mgmt_subnet, strict=False) return f"{subnet[1]!s}" @cached_property @@ -104,13 +87,16 @@ def inband_mgmt_ipv6_gateway(self: SharedUtils) -> str | None: Otherwise return None """ - if self.inband_mgmt_ipv6_address is None: + if not self.inband_mgmt_ipv6_address: return None if not self.configure_parent_for_inband_mgmt_ipv6: - return get(self.switch_data_combined, "inband_mgmt_ipv6_gateway") + return self.node_config.inband_mgmt_ipv6_gateway + + if not self.node_config.inband_mgmt_ipv6_subnet: + return None - subnet = ip_network(self.inband_mgmt_ipv6_subnet, strict=False) + subnet = ip_network(self.node_config.inband_mgmt_ipv6_subnet, strict=False) return f"{subnet[1]!s}" @cached_property @@ -123,17 +109,17 @@ def inband_mgmt_ip(self: SharedUtils) -> str | None: - deducted IP from inband_mgmt_subnet & id - None. """ - if (inband_mgmt_ip := get(self.switch_data_combined, "inband_mgmt_ip")) is not None: + if inband_mgmt_ip := self.node_config.inband_mgmt_ip: return inband_mgmt_ip - if self.inband_mgmt_subnet is None: + if not self.node_config.inband_mgmt_subnet: return None if self.id is None: msg = f"'id' is not set on '{self.hostname}' and is required to set inband_mgmt_ip from inband_mgmt_subnet" raise AristaAvdInvalidInputsError(msg) - subnet = ip_network(self.inband_mgmt_subnet, strict=False) + subnet = ip_network(self.node_config.inband_mgmt_subnet, strict=False) inband_mgmt_ip = str(subnet[3 + self.id]) return f"{inband_mgmt_ip}/{subnet.prefixlen}" @@ -147,17 +133,17 @@ def inband_mgmt_ipv6_address(self: SharedUtils) -> str | None: - deduced IP from inband_mgmt_ipv6_subnet & id - None. """ - if (inband_mgmt_ipv6_address := get(self.switch_data_combined, "inband_mgmt_ipv6_address")) is not None: + if inband_mgmt_ipv6_address := self.node_config.inband_mgmt_ipv6_address: return inband_mgmt_ipv6_address - if self.inband_mgmt_ipv6_subnet is None: + if not self.node_config.inband_mgmt_ipv6_subnet: return None if self.id is None: msg = f"'id' is not set on '{self.hostname}' and is required to set inband_mgmt_ipv6_address from inband_mgmt_ipv6_subnet" raise AristaAvdInvalidInputsError(msg) - subnet = ip_network(self.inband_mgmt_ipv6_subnet, strict=False) + subnet = ip_network(self.node_config.inband_mgmt_ipv6_subnet, strict=False) inband_mgmt_ipv6_address = str(subnet[3 + self.id]) return f"{inband_mgmt_ipv6_address}/{subnet.prefixlen}" @@ -169,22 +155,14 @@ def inband_mgmt_interface(self: SharedUtils) -> str | None: For L2 switches defaults to Vlan For all other devices set to value of inband_mgmt_interface or None """ - if (inband_mgmt_interface := get(self.switch_data_combined, "inband_mgmt_interface")) is not None: + if inband_mgmt_interface := self.node_config.inband_mgmt_interface: return inband_mgmt_interface if self.configure_inband_mgmt or self.configure_inband_mgmt_ipv6: - return f"Vlan{self.inband_mgmt_vlan}" + return f"Vlan{self.node_config.inband_mgmt_vlan}" return None - @cached_property - def inband_ztp(self: SharedUtils) -> bool | None: - return get(self.switch_data_combined, "inband_ztp") - - @cached_property - def inband_ztp_lacp_fallback_delay(self: SharedUtils) -> int | None: - return default(get(self.switch_data_combined, "inband_ztp_lacp_fallback_delay"), 30) - @cached_property def inband_management_parent_vlans(self: SharedUtils) -> dict: if not self.underlay_router: diff --git a/python-avd/pyavd/_eos_designs/shared_utils/interface_descriptions.py b/python-avd/pyavd/_eos_designs/shared_utils/interface_descriptions.py index a0e410b4f5c..7c044e30148 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/interface_descriptions.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/interface_descriptions.py @@ -6,14 +6,12 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import get, load_python_class, merge +from pyavd._utils import load_python_class from pyavd.api.interface_descriptions import AvdInterfaceDescriptions if TYPE_CHECKING: from . import SharedUtils -DEFAULT_AVD_INTERFACE_DESCRIPTIONS_PYTHON_CLASS_NAME = "AvdInterfaceDescriptions" - class InterfaceDescriptionsMixin: """ @@ -30,32 +28,14 @@ def interface_descriptions(self: SharedUtils) -> AvdInterfaceDescriptions: Return an instance of the class defined by `templates.interface_descriptions.python_class_name` as cached_property. """ - module_path = self.interface_descriptions_templates.get("python_module") + module_path = self.node_type_key_data.interface_descriptions.python_module if module_path is None: - return AvdInterfaceDescriptions(hostvars=self.hostvars, shared_utils=self) - - class_name = self.interface_descriptions_templates.get("python_class_name", DEFAULT_AVD_INTERFACE_DESCRIPTIONS_PYTHON_CLASS_NAME) + return AvdInterfaceDescriptions(hostvars=self.hostvars, inputs=self.inputs, shared_utils=self) - cls = load_python_class( + cls: type[AvdInterfaceDescriptions] = load_python_class( module_path, - class_name, + self.node_type_key_data.interface_descriptions.python_class_name, AvdInterfaceDescriptions, ) - return cls(hostvars=self.hostvars, shared_utils=self) - - @cached_property - def interface_descriptions_templates(self: SharedUtils) -> dict: - """ - Return dict with interface_descriptions templates. - - Set based on - templates.interface_descriptions.* combined with (overridden by) - node_type_keys..interface_descriptions.*. - """ - hostvar_templates = get(self.hostvars, "templates.interface_descriptions", default={}) - node_type_templates = get(self.node_type_key_data, "interface_descriptions", default={}) - if hostvar_templates or node_type_templates: - return merge(hostvar_templates, node_type_templates, list_merge="replace", destructive_merge=False) - - return {} + return cls(hostvars=self.hostvars, inputs=self.inputs, shared_utils=self) diff --git a/python-avd/pyavd/_eos_designs/shared_utils/ip_addressing.py b/python-avd/pyavd/_eos_designs/shared_utils/ip_addressing.py index e745dad3875..550c44870a8 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/ip_addressing.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/ip_addressing.py @@ -6,14 +6,13 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import get, load_python_class, merge +from pyavd._errors import AristaAvdMissingVariableError +from pyavd._utils import load_python_class from pyavd.api.ip_addressing import AvdIpAddressing if TYPE_CHECKING: from . import SharedUtils -DEFAULT_AVD_IP_ADDRESSING_PYTHON_CLASS_NAME = "AvdIpAddressing" - class IpAddressingMixin: """ @@ -23,43 +22,29 @@ class IpAddressingMixin: Using type-hint on self to get proper type-hints on attributes across all Mixins. """ - @cached_property - def loopback_ipv4_offset(self: SharedUtils) -> int: - return get(self.switch_data_combined, "loopback_ipv4_offset", default=0) - - @cached_property - def loopback_ipv6_offset(self: SharedUtils) -> int: - return get(self.switch_data_combined, "loopback_ipv6_offset", default=0) - @cached_property def loopback_ipv6_pool(self: SharedUtils) -> str: - return get(self.switch_data_combined, "loopback_ipv6_pool", required=True) + if not self.node_config.loopback_ipv6_pool: + msg = "loopback_ipv6_pool" + raise AristaAvdMissingVariableError(msg) - @cached_property - def uplink_ipv4_pool(self: SharedUtils) -> str | None: - return get(self.switch_data_combined, "uplink_ipv4_pool") - - @cached_property - def downlink_pools(self: SharedUtils) -> list | None: - return get(self.switch_data_combined, "downlink_pools") + return self.node_config.loopback_ipv6_pool @cached_property def loopback_ipv4_pool(self: SharedUtils) -> str: - return get(self.switch_data_combined, "loopback_ipv4_pool", required=True) + if not self.node_config.loopback_ipv4_pool: + msg = "loopback_ipv4_pool" + raise AristaAvdMissingVariableError(msg) - @cached_property - def loopback_ipv4_address(self: SharedUtils) -> str: - """Set the loopback IPv4 for this host, takes precedence over loopback_ipv4_pool.""" - return get(self.switch_data_combined, "loopback_ipv4_address") + return self.node_config.loopback_ipv4_pool @cached_property def vtep_loopback_ipv4_pool(self: SharedUtils) -> str: - return get(self.switch_data_combined, "vtep_loopback_ipv4_pool", required=True) + if not self.node_config.vtep_loopback_ipv4_pool: + msg = "vtep_loopback_ipv4_pool" + raise AristaAvdMissingVariableError(msg) - @cached_property - def vtep_loopback_ipv4_address(self: SharedUtils) -> str: - """Set the VTEP loopback IPv4 for this host, takes precedence over vtep_loopback_ipv4_pool.""" - return get(self.switch_data_combined, "vtep_loopback_ipv4_address") + return self.node_config.vtep_loopback_ipv4_pool @cached_property def vtep_ip(self: SharedUtils) -> str: @@ -69,10 +54,6 @@ def vtep_ip(self: SharedUtils) -> str: return self.ip_addressing.vtep_ip() - @cached_property - def vtep_vvtep_ip(self: SharedUtils) -> str | None: - return get(self.hostvars, "vtep_vvtep_ip") - @cached_property def ip_addressing(self: SharedUtils) -> AvdIpAddressing: """ @@ -80,32 +61,14 @@ def ip_addressing(self: SharedUtils) -> AvdIpAddressing: Return an instance of the class defined by `templates.ip_addressing.python_class_name` as cached_property. """ - module_path = self.ip_addressing_templates.get("python_module") + module_path = self.node_type_key_data.ip_addressing.python_module if module_path is None: - return AvdIpAddressing(hostvars=self.hostvars, shared_utils=self) - - class_name = self.ip_addressing_templates.get("python_class_name", DEFAULT_AVD_IP_ADDRESSING_PYTHON_CLASS_NAME) + return AvdIpAddressing(hostvars=self.hostvars, inputs=self.inputs, shared_utils=self) - cls = load_python_class( + cls: type[AvdIpAddressing] = load_python_class( module_path, - class_name, + self.node_type_key_data.ip_addressing.python_class_name, AvdIpAddressing, ) - return cls(hostvars=self.hostvars, shared_utils=self) - - @cached_property - def ip_addressing_templates(self: SharedUtils) -> dict: - """ - Return dict with ip_addressing templates. - - Set based on - templates.ip_addressing.* combined with (overridden by) - node_type_keys..ip_addressing.*. - """ - hostvar_templates = get(self.hostvars, "templates.ip_addressing", default={}) - node_type_templates = get(self.node_type_key_data, "ip_addressing", default={}) - if hostvar_templates or node_type_templates: - return merge(hostvar_templates, node_type_templates, list_merge="replace", destructive_merge=False) - - return {} + return cls(hostvars=self.hostvars, inputs=self.inputs, shared_utils=self) diff --git a/python-avd/pyavd/_eos_designs/shared_utils/l3_interfaces.py b/python-avd/pyavd/_eos_designs/shared_utils/l3_interfaces.py index 1d4a8f415d9..61537193d91 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/l3_interfaces.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/l3_interfaces.py @@ -6,8 +6,8 @@ from functools import cached_property from typing import TYPE_CHECKING +from pyavd._eos_designs.schema import EosDesigns from pyavd._errors import AristaAvdInvalidInputsError -from pyavd._utils import get, get_item, merge from pyavd.api.interface_descriptions import InterfaceDescriptionData if TYPE_CHECKING: @@ -31,76 +31,69 @@ def sanitize_interface_name(self: SharedUtils, interface_name: str) -> str: """ return interface_name.replace("/", "_") - def apply_l3_interfaces_profile(self: SharedUtils, l3_interface: dict) -> dict: + def apply_l3_interfaces_profile( + self: SharedUtils, l3_interface: EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem.L3InterfacesItem + ) -> EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem.L3InterfacesItem: """Apply a profile to an l3_interface.""" - if "profile" not in l3_interface: + if not l3_interface.profile: # Nothing to do return l3_interface - msg = f"Profile '{l3_interface['profile']}' applied under l3_interface '{l3_interface['name']}' does not exist in `l3_interface_profiles`." - profile = get_item(self.l3_interface_profiles, "profile", l3_interface["profile"], required=True, custom_error_msg=msg) - merged_dict: dict = merge(profile, l3_interface, list_merge="replace", destructive_merge=False) - merged_dict.pop("profile", None) - return merged_dict + if l3_interface.profile not in self.inputs.l3_interface_profiles: + msg = f"Profile '{l3_interface.profile}' applied under l3_interface '{l3_interface.name}' does not exist in `l3_interface_profiles`." + raise AristaAvdInvalidInputsError(msg) - @cached_property - def l3_interface_profiles(self: SharedUtils) -> list: - return get(self.hostvars, "l3_interface_profiles", default=[]) + profile_as_interface = self.inputs.l3_interface_profiles[l3_interface.profile]._cast_as( + EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem.L3InterfacesItem + ) + return l3_interface._deepinherited(profile_as_interface) @cached_property - def l3_interfaces(self: SharedUtils) -> list: + def l3_interfaces(self: SharedUtils) -> EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem.L3Interfaces: """Returns the list of l3_interfaces, where any referenced profiles are applied.""" - if not (l3_interfaces := get(self.switch_data_combined, "l3_interfaces")): - return [] - - # Apply l3_interfaces._profile if set. - if self.l3_interface_profiles: - l3_interfaces = [self.apply_l3_interfaces_profile(l3_interface) for l3_interface in l3_interfaces] - - return l3_interfaces + return EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem.L3Interfaces( + [self.apply_l3_interfaces_profile(l3_interface) for l3_interface in self.node_config.l3_interfaces] + ) @cached_property def l3_interfaces_bgp_neighbors(self: SharedUtils) -> list: neighbors = [] for interface in self.l3_interfaces: - peer_ip = get(interface, "peer_ip") - bgp = get(interface, "bgp") - if not (peer_ip and bgp): + if not (interface.peer_ip and interface.bgp): continue - peer_as = get(bgp, "peer_as") + peer_as = interface.bgp.peer_as if peer_as is None: - msg = f"'l3_interfaces[{interface['name']}].bgp.peer_as' needs to be set to enable BGP." + msg = f"'l3_interfaces[{interface.name}].bgp.peer_as' needs to be set to enable BGP." raise AristaAvdInvalidInputsError(msg) - is_intf_wan = get(interface, "wan_carrier") is not None + is_intf_wan = bool(interface.wan_carrier) - prefix_list_in = get(bgp, "ipv4_prefix_list_in") - if prefix_list_in is None and is_intf_wan: - msg = f"BGP is enabled but 'bgp.ipv4_prefix_list_in' is not configured for l3_interfaces[{interface['name']}]" + if not interface.bgp.ipv4_prefix_list_in and is_intf_wan: + msg = f"BGP is enabled but 'bgp.ipv4_prefix_list_in' is not configured for l3_interfaces[{interface.name}]" raise AristaAvdInvalidInputsError(msg) - description = interface.get("description") + description = interface.description if not description: description = self.interface_descriptions.underlay_ethernet_interface( InterfaceDescriptionData( shared_utils=self, - interface=interface["name"], - peer=interface.get("peer"), - peer_interface=interface.get("peer_interface"), - wan_carrier=interface.get("wan_carrier"), - wan_circuit_id=interface.get("wan_circuit_id"), + interface=interface.name, + peer=interface.peer, + peer_interface=interface.peer_interface, + wan_carrier=interface.wan_carrier, + wan_circuit_id=interface.wan_circuit_id, ), ) neighbor = { - "ip_address": peer_ip, + "ip_address": interface.peer_ip, "remote_as": peer_as, "description": description, } - neighbor["ipv4_prefix_list_in"] = prefix_list_in - neighbor["ipv4_prefix_list_out"] = get(bgp, "ipv4_prefix_list_out") + neighbor["ipv4_prefix_list_in"] = interface.bgp.ipv4_prefix_list_in + neighbor["ipv4_prefix_list_out"] = interface.bgp.ipv4_prefix_list_out if is_intf_wan: neighbor["set_no_advertise"] = True diff --git a/python-avd/pyavd/_eos_designs/shared_utils/link_tracking_groups.py b/python-avd/pyavd/_eos_designs/shared_utils/link_tracking_groups.py index 8aa87d70486..0782dd521af 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/link_tracking_groups.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/link_tracking_groups.py @@ -6,7 +6,7 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import get +from pyavd._utils import default if TYPE_CHECKING: from . import SharedUtils @@ -22,15 +22,14 @@ class LinkTrackingGroupsMixin: @cached_property def link_tracking_groups(self: SharedUtils) -> list | None: - if get(self.switch_data_combined, "link_tracking.enabled") is True: + if self.node_config.link_tracking.enabled: link_tracking_groups = [] - default_recovery_delay = get(self.platform_settings, "reload_delay.mlag", 300) - lt_groups = get(self.switch_data_combined, "link_tracking.groups", default=[]) - - if len(lt_groups) > 0: - for lt_group in lt_groups: - lt_group["recovery_delay"] = lt_group.get("recovery_delay", default_recovery_delay) - link_tracking_groups.append(lt_group) + default_recovery_delay = default(self.platform_settings.reload_delay.mlag, 300) + if len(self.node_config.link_tracking.groups) > 0: + for lt_group in self.node_config.link_tracking.groups: + lt_group_dict = lt_group._as_dict(include_default_values=True) + lt_group_dict["recovery_delay"] = default(lt_group.recovery_delay, default_recovery_delay) + link_tracking_groups.append(lt_group_dict) else: link_tracking_groups.append({"name": "LT_GROUP1", "recovery_delay": default_recovery_delay}) diff --git a/python-avd/pyavd/_eos_designs/shared_utils/mgmt.py b/python-avd/pyavd/_eos_designs/shared_utils/mgmt.py index 5ef29601f15..6cb64c38fbb 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/mgmt.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/mgmt.py @@ -22,7 +22,7 @@ class MgmtMixin: """ @cached_property - def mgmt_interface(self: SharedUtils) -> str | None: + def mgmt_interface(self: SharedUtils) -> str: """ mgmt_interface. @@ -32,32 +32,22 @@ def mgmt_interface(self: SharedUtils) -> str | None: Fabric Topology data model mgmt_interface. """ return default( - get(self.switch_data_combined, "mgmt_interface"), - self.platform_settings.get("management_interface"), - get(self.hostvars, "mgmt_interface"), + self.node_config.mgmt_interface, + # Notice that we actually have a default value for the next two, but the precedence order would break if we use it. + # TODO: Evaluate if we should remove the default values from either or both. + self.platform_settings._get("management_interface", None), + self.inputs._get("mgmt_interface", None), get(self.cv_topology_config, "mgmt_interface"), "Management1", ) - @cached_property - def ipv6_mgmt_ip(self: SharedUtils) -> str | None: - return get(self.switch_data_combined, "ipv6_mgmt_ip") - - @cached_property - def mgmt_ip(self: SharedUtils) -> str | None: - return get(self.switch_data_combined, "mgmt_ip") - - @cached_property - def mgmt_interface_vrf(self: SharedUtils) -> str: - return get(self.hostvars, "mgmt_interface_vrf", default="MGMT") - @cached_property def mgmt_gateway(self: SharedUtils) -> str | None: - return get(self.switch_data_combined, "mgmt_gateway", default=get(self.hostvars, "mgmt_gateway")) + return default(self.node_config.mgmt_gateway, self.inputs.mgmt_gateway) @cached_property def ipv6_mgmt_gateway(self: SharedUtils) -> str | None: - return get(self.switch_data_combined, "ipv6_mgmt_gateway", default=get(self.hostvars, "ipv6_mgmt_gateway")) + return default(self.node_config.ipv6_mgmt_gateway, self.inputs.ipv6_mgmt_gateway) @cached_property def default_mgmt_method(self: SharedUtils) -> str | None: @@ -66,10 +56,10 @@ def default_mgmt_method(self: SharedUtils) -> str | None: The check for 'inband_mgmt_interface' relies on other indirect checks done in that code. """ - default_mgmt_method = get(self.hostvars, "default_mgmt_method", default="oob") + default_mgmt_method = self.inputs.default_mgmt_method if default_mgmt_method == "oob": - if (self.mgmt_ip is None) and (self.ipv6_mgmt_ip is None): - msg = "'default_mgmt_method: oob' requires either 'mgmt_ip' or 'ipv6_mgmt_ip' to bet set." + if self.node_config.mgmt_ip is None and self.node_config.ipv6_mgmt_ip is None: + msg = "'default_mgmt_method: oob' requires either 'mgmt_ip' or 'ipv6_mgmt_ip' to be set." raise AristaAvdInvalidInputsError(msg) return default_mgmt_method @@ -87,7 +77,7 @@ def default_mgmt_method(self: SharedUtils) -> str | None: @cached_property def default_mgmt_protocol_vrf(self: SharedUtils) -> str | None: if self.default_mgmt_method == "oob": - return self.mgmt_interface_vrf + return self.inputs.mgmt_interface_vrf if self.default_mgmt_method == "inband": # inband_mgmt_vrf returns None for vrf default. return self.inband_mgmt_vrf or "default" diff --git a/python-avd/pyavd/_eos_designs/shared_utils/misc.py b/python-avd/pyavd/_eos_designs/shared_utils/misc.py index 3cb758d12f3..bf7a7b88ac7 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/misc.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/misc.py @@ -3,16 +3,16 @@ # that can be found in the LICENSE file. from __future__ import annotations -from copy import deepcopy from functools import cached_property from typing import TYPE_CHECKING, Any -from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError +from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError, AristaAvdMissingVariableError from pyavd._utils import default, get -from pyavd.j2filters import natural_sort, range_expand +from pyavd.j2filters import range_expand if TYPE_CHECKING: from pyavd._eos_designs.eos_designs_facts import EosDesignsFacts + from pyavd._eos_designs.schema import EosDesigns from . import SharedUtils @@ -32,65 +32,28 @@ def all_fabric_devices(self: SharedUtils) -> list[str]: @cached_property def hostname(self: SharedUtils) -> str: - """Hostname set based on inventory_hostname variable.""" + """Hostname set based on inventory_hostname variable. TODO: Get a proper attribute on the class instead of gleaning from the regular inputs.""" return get(self.hostvars, "inventory_hostname", required=True) - @cached_property - def is_deployed(self: SharedUtils) -> bool: - return get(self.hostvars, "is_deployed", default=True) - @cached_property def id(self: SharedUtils) -> int | None: - return get(self.switch_data_combined, "id") - - @cached_property - def trunk_groups(self: SharedUtils) -> dict: - return { - "mlag": {"name": get(self.hostvars, "trunk_groups.mlag.name", default="MLAG")}, - "mlag_l3": {"name": get(self.hostvars, "trunk_groups.mlag_l3.name", default="MLAG")}, - "uplink": {"name": get(self.hostvars, "trunk_groups.uplink.name", default="UPLINK")}, - } - - @cached_property - def enable_trunk_groups(self: SharedUtils) -> bool: - return get(self.hostvars, "enable_trunk_groups", default=False) - - @cached_property - def filter_only_vlans_in_use(self: SharedUtils) -> bool: - return get(self.switch_data_combined, "filter.only_vlans_in_use", default=False) + return self.node_config.id @cached_property def filter_tags(self: SharedUtils) -> list: """Return filter.tags + group if defined.""" - filter_tags = get(self.switch_data_combined, "filter.tags", default=["all"]) + filter_tags = self.node_config.filter.tags if self.group is not None: filter_tags.append(self.group) return filter_tags - @cached_property - def filter_allow_vrfs(self: SharedUtils) -> list: - return get(self.switch_data_combined, "filter.allow_vrfs", default=["all"]) - - @cached_property - def filter_deny_vrfs(self: SharedUtils) -> list: - return get(self.switch_data_combined, "filter.deny_vrfs", default=[]) - - @cached_property - def filter_tenants(self: SharedUtils) -> list: - return get(self.switch_data_combined, "filter.tenants", default=["all"]) - - @cached_property - def always_include_vrfs_in_tenants(self: SharedUtils) -> list: - return get(self.switch_data_combined, "filter.always_include_vrfs_in_tenants", default=[]) - @cached_property def igmp_snooping_enabled(self: SharedUtils) -> bool: - default_igmp_snooping_enabled = get(self.hostvars, "default_igmp_snooping_enabled", default=True) - return get(self.switch_data_combined, "igmp_snooping_enabled", default=default_igmp_snooping_enabled) is True + 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: - return self.enable_trunk_groups and get(self.hostvars, "only_local_vlan_trunk_groups", default=False) + return self.inputs.enable_trunk_groups and self.inputs.only_local_vlan_trunk_groups @cached_property def system_mac_address(self: SharedUtils) -> str | None: @@ -101,34 +64,22 @@ def system_mac_address(self: SharedUtils) -> str | None: Fabric Topology data model system_mac_address -> Host variable var system_mac_address ->. """ - return default(get(self.switch_data_combined, "system_mac_address"), get(self.hostvars, "system_mac_address")) + return default(self.node_config.system_mac_address, self.inputs.system_mac_address) @cached_property - def uplink_switches(self: SharedUtils) -> list: - return default( - get(self.switch_data_combined, "uplink_switches"), - get(self.cv_topology_config, "uplink_switches"), - [], - ) + def uplink_switches(self: SharedUtils) -> list[str]: + return self.node_config.uplink_switches._as_list() or get(self.cv_topology_config, "uplink_switches") or [] @cached_property - def uplink_interfaces(self: SharedUtils) -> list: + def uplink_interfaces(self: SharedUtils) -> list[str]: return range_expand( - default( - get(self.switch_data_combined, "uplink_interfaces"), - get(self.cv_topology_config, "uplink_interfaces"), - get(self.default_interfaces, "uplink_interfaces"), - [], - ), + self.node_config.uplink_interfaces or get(self.cv_topology_config, "uplink_interfaces") or self.default_interfaces.uplink_interfaces, ) @cached_property - def uplink_switch_interfaces(self: SharedUtils) -> list: - uplink_switch_interfaces = default( - get(self.switch_data_combined, "uplink_switch_interfaces"), - get(self.cv_topology_config, "uplink_switch_interfaces"), - ) - if uplink_switch_interfaces is not None: + def uplink_switch_interfaces(self: SharedUtils) -> list[str]: + uplink_switch_interfaces = self.node_config.uplink_switch_interfaces or get(self.cv_topology_config, "uplink_switch_interfaces") or [] + if uplink_switch_interfaces: return range_expand(uplink_switch_interfaces) if not self.uplink_switches: @@ -150,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: @@ -158,16 +109,10 @@ def uplink_switch_interfaces(self: SharedUtils) -> list: f"'uplink_switch_interfaces' is not set on '{self.hostname}' and 'uplink_switch' '{uplink_switch}' " f"does not have 'downlink_interfaces[{downlink_index}]' set under 'default_interfaces'" ) - raise AristaAvdError( - msg, - ) + raise AristaAvdError(msg) return uplink_switch_interfaces - @cached_property - def virtual_router_mac_address(self: SharedUtils) -> str | None: - return get(self.switch_data_combined, "virtual_router_mac_address") - @cached_property def serial_number(self: SharedUtils) -> str | None: """ @@ -177,180 +122,41 @@ def serial_number(self: SharedUtils) -> str | None: Fabric Topology data model serial_number -> Host variable var serial_number. """ - return default(get(self.switch_data_combined, "serial_number"), get(self.hostvars, "serial_number")) - - @cached_property - def max_parallel_uplinks(self: SharedUtils) -> int: - """Exposed in avd_switch_facts.""" - return get(self.switch_data_combined, "max_parallel_uplinks", default=1) + return default(self.node_config.serial_number, self.inputs.serial_number) @cached_property def max_uplink_switches(self: SharedUtils) -> int: """max_uplink_switches will default to the length of uplink_switches.""" - return get(self.switch_data_combined, "max_uplink_switches", default=len(self.uplink_switches)) + return default(self.node_config.max_uplink_switches, len(self.uplink_switches)) @cached_property def p2p_uplinks_mtu(self: SharedUtils) -> int | None: - if not self.platform_settings_feature_support_per_interface_mtu: + if not self.platform_settings.feature_support.per_interface_mtu: return None - p2p_uplinks_mtu = default(self.platform_settings_p2p_uplinks_mtu, get(self.hostvars, "p2p_uplinks_mtu", default=9214)) - return get(self.switch_data_combined, "uplink_mtu", default=p2p_uplinks_mtu) - - @cached_property - def evpn_short_esi_prefix(self: SharedUtils) -> str: - return get(self.hostvars, "evpn_short_esi_prefix", default="0000:0000:") - - @cached_property - def shutdown_interfaces_towards_undeployed_peers(self: SharedUtils) -> bool: - return get(self.hostvars, "shutdown_interfaces_towards_undeployed_peers", default=True) is True - - @cached_property - def shutdown_bgp_towards_undeployed_peers(self: SharedUtils) -> bool: - return get(self.hostvars, "shutdown_bgp_towards_undeployed_peers", default=True) is True - - @cached_property - def bfd_multihop(self: SharedUtils) -> dict: - default_bfd_multihop = { - "interval": 300, - "min_rx": 300, - "multiplier": 3, - } - return get(self.hostvars, "bfd_multihop", default=default_bfd_multihop) - - @cached_property - def evpn_ebgp_multihop(self: SharedUtils) -> int: - return get(self.hostvars, "evpn_ebgp_multihop", default=3) - - @cached_property - def evpn_ebgp_gateway_multihop(self: SharedUtils) -> int: - return get(self.hostvars, "evpn_ebgp_gateway_multihop", default=15) - - @cached_property - def evpn_overlay_bgp_rtc(self: SharedUtils) -> bool: - return get(self.hostvars, "evpn_overlay_bgp_rtc") is True - - @cached_property - def evpn_prevent_readvertise_to_server(self: SharedUtils) -> bool: - return get(self.hostvars, "evpn_prevent_readvertise_to_server") is True - - @cached_property - def dc_name(self: SharedUtils) -> str | None: - return get(self.hostvars, "dc_name") + p2p_uplinks_mtu = default(self.platform_settings.p2p_uplinks_mtu, self.inputs.p2p_uplinks_mtu) + return default(self.node_config.uplink_mtu, p2p_uplinks_mtu) @cached_property def fabric_name(self: SharedUtils) -> str: - return get(self.hostvars, "fabric_name", required=True) - - @cached_property - def rack(self: SharedUtils) -> str | None: - return get(self.switch_data_combined, "rack") - - @cached_property - def network_services_keys(self: SharedUtils) -> list[dict]: - """ - Return sorted network_services_keys filtered for invalid entries and unused keys. - - NOTE: This method is called _before_ any schema validation, since we need to resolve network_services_keys dynamically - """ - # Reading default value from schema - default_network_services_keys = self.schema.get_default_value(["network_services_keys"]) - network_services_keys = get(self.hostvars, "network_services_keys", default=default_network_services_keys) - network_services_keys = [entry for entry in network_services_keys if entry.get("name") is not None and self.hostvars.get(entry["name"]) is not None] - return natural_sort(network_services_keys, "name") + if not self.inputs.fabric_name: + msg = "fabric_name" + raise AristaAvdMissingVariableError(msg) - @cached_property - def port_profiles(self: SharedUtils) -> list: - return get(self.hostvars, "port_profiles", default=[]) + return self.inputs.fabric_name @cached_property def uplink_interface_speed(self: SharedUtils) -> str | None: - return get(self.switch_data_combined, "uplink_interface_speed") + # Keeping since we will need it when adding speed support under default interfaces. + return self.node_config.uplink_interface_speed @cached_property def uplink_switch_interface_speed(self: SharedUtils) -> str | None: - return get(self.switch_data_combined, "uplink_switch_interface_speed") - - @cached_property - def uplink_bfd(self: SharedUtils) -> bool: - return get(self.switch_data_combined, "uplink_bfd") is True - - @cached_property - def uplink_ptp(self: SharedUtils) -> dict | None: - return get(self.switch_data_combined, "uplink_ptp") - - @cached_property - def uplink_macsec(self: SharedUtils) -> dict | None: - return get(self.switch_data_combined, "uplink_macsec") - - @cached_property - def uplink_structured_config(self: SharedUtils) -> dict | None: - return get(self.switch_data_combined, "uplink_structured_config") - - @cached_property - def p2p_uplinks_qos_profile(self: SharedUtils) -> str | None: - return get(self.hostvars, "p2p_uplinks_qos_profile") - - @cached_property - def isis_default_metric(self: SharedUtils) -> int: - return get(self.hostvars, "isis_default_metric", default=50) - - @cached_property - def isis_default_circuit_type(self: SharedUtils) -> str | None: - return get(self.hostvars, "isis_default_circuit_type", default="level-2") - - @cached_property - def pod_name(self: SharedUtils) -> str | None: - return get(self.hostvars, "pod_name") - - @cached_property - def fabric_ip_addressing_mlag_algorithm(self: SharedUtils) -> str: - """ - This method fetches the MLAG algorithm value from host variables. - - It defaults to 'first_id' if the variable is not defined. - """ - return get(self.hostvars, "fabric_ip_addressing.mlag.algorithm", default="first_id") - - @cached_property - def fabric_ip_addressing_mlag_ipv4_prefix_length(self: SharedUtils) -> int: - return get(self.hostvars, "fabric_ip_addressing.mlag.ipv4_prefix_length", default=31) - - @cached_property - def fabric_ip_addressing_mlag_ipv6_prefix_length(self: SharedUtils) -> int: - return get(self.hostvars, "fabric_ip_addressing.mlag.ipv6_prefix_length", default=64) - - @cached_property - def fabric_ip_addressing_p2p_uplinks_ipv4_prefix_length(self: SharedUtils) -> int: - return get(self.hostvars, "fabric_ip_addressing.p2p_uplinks.ipv4_prefix_length", default=31) - - @cached_property - def fabric_ip_addressing_wan_ha_ipv4_prefix_length(self: SharedUtils) -> int: - return get(self.hostvars, "fabric_ip_addressing.wan_ha.ipv4_prefix_length", default=31) - - @cached_property - def fabric_sflow_uplinks(self: SharedUtils) -> bool | None: - return get(self.hostvars, "fabric_sflow.uplinks") - - @cached_property - def fabric_sflow_downlinks(self: SharedUtils) -> bool | None: - return get(self.hostvars, "fabric_sflow.downlinks") - - @cached_property - def fabric_sflow_endpoints(self: SharedUtils) -> bool | None: - return get(self.hostvars, "fabric_sflow.endpoints") - - @cached_property - def fabric_sflow_mlag_interfaces(self: SharedUtils) -> bool | None: - return get(self.hostvars, "fabric_sflow.mlag_interfaces") - - @cached_property - def fabric_sflow_l3_interfaces(self: SharedUtils) -> bool | None: - return get(self.hostvars, "fabric_sflow.l3_interfaces") + # Keeping since we will need it when adding speed support under default interfaces. + return self.node_config.uplink_switch_interface_speed @cached_property def default_interface_mtu(self: SharedUtils) -> int | None: - default_default_interface_mtu = get(self.hostvars, "default_interface_mtu") - return get(self.platform_settings, "default_interface_mtu", default=default_default_interface_mtu) + return default(self.platform_settings.default_interface_mtu, self.inputs.default_interface_mtu) def get_switch_fact(self: SharedUtils, key: str, required: bool = True) -> Any: """ @@ -364,35 +170,41 @@ def get_switch_fact(self: SharedUtils, key: str, required: bool = True) -> Any: def evpn_multicast(self: SharedUtils) -> bool: return self.get_switch_fact("evpn_multicast", required=False) is True - @cached_property - def ipv4_acls(self: SharedUtils) -> dict: - return {acl["name"]: acl for acl in get(self.hostvars, "ipv4_acls", default=[])} - - def get_ipv4_acl(self: SharedUtils, name: str, interface_name: str, *, interface_ip: str | None = None, peer_ip: str | None = None) -> dict: + def get_ipv4_acl( + self: SharedUtils, name: str, interface_name: str, *, interface_ip: str | None = None, peer_ip: str | None = None + ) -> EosDesigns.Ipv4AclsItem: """ Get one IPv4 ACL from "ipv4_acls" where fields have been substituted. If any substitution is done, the ACL name will get "_" appended. """ - org_ipv4_acl = get(self.ipv4_acls, name, required=True, org_key=f"ipv4_acls[name={name}]") + if name not in self.inputs.ipv4_acls: + msg = f"ipv4_acls[name={name}]" + raise AristaAvdMissingVariableError(msg) + org_ipv4_acl = self.inputs.ipv4_acls[name] # deepcopy to avoid inplace updates below from modifying the original. - ipv4_acl = deepcopy(org_ipv4_acl) + ipv4_acl = org_ipv4_acl._deepcopy() ip_replacements = { "interface_ip": interface_ip, "peer_ip": peer_ip, } - for index, entry in enumerate(get(ipv4_acl, "entries", default=[])): - if entry.get("remark") is not None: + for index, entry in enumerate(ipv4_acl.entries): + if entry._get("remark"): continue err_context = f"ipv4_acls[name={name}].entries[{index}]" - source_field = get(entry, "source", required=True, org_key=f"{err_context}.source") - destination_field = get(entry, "destination", required=True, org_key=f"{err_context}.destination") - entry["source"] = self._get_ipv4_acl_field_with_substitution(source_field, ip_replacements, f"{err_context}.source", interface_name) - entry["destination"] = self._get_ipv4_acl_field_with_substitution(destination_field, ip_replacements, f"{err_context}.destination", interface_name) + if not entry.source: + msg = f"{err_context}.source" + raise AristaAvdMissingVariableError(msg) + if not entry.destination: + msg = f"{err_context}.destination" + raise AristaAvdMissingVariableError(msg) + + entry.source = self._get_ipv4_acl_field_with_substitution(entry.source, ip_replacements, f"{err_context}.source", interface_name) + entry.destination = self._get_ipv4_acl_field_with_substitution(entry.destination, ip_replacements, f"{err_context}.destination", interface_name) if ipv4_acl != org_ipv4_acl: - ipv4_acl["name"] += f"_{self.sanitize_interface_name(interface_name)}" + ipv4_acl.name += f"_{self.sanitize_interface_name(interface_name)}" return ipv4_acl @staticmethod @@ -416,18 +228,8 @@ def _get_ipv4_acl_field_with_substitution(field_value: str, replacements: dict[s f"since no substitution value was found for interface '{interface_name}'. " "Make sure to set the appropriate fields on the interface." ) - raise AristaAvdError( - msg, - ) + raise AristaAvdError(msg) return value return field_value - - @cached_property - def ipv4_prefix_list_catalog(self: SharedUtils) -> list: - return get(self.hostvars, "ipv4_prefix_list_catalog", default=[]) - - @cached_property - def use_router_general_for_router_id(self: SharedUtils) -> bool: - return bool(get(self.hostvars, "use_router_general_for_router_id")) diff --git a/python-avd/pyavd/_eos_designs/shared_utils/mlag.py b/python-avd/pyavd/_eos_designs/shared_utils/mlag.py index 789db8f19fe..b7282713a66 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/mlag.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/mlag.py @@ -7,11 +7,13 @@ from re import findall from typing import TYPE_CHECKING, Any -from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError +from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError, AristaAvdMissingVariableError from pyavd._utils import default, get, get_ip_from_ip_prefix from pyavd.j2filters import range_expand if TYPE_CHECKING: + from typing import Literal + from pyavd._eos_designs.eos_designs_facts import EosDesignsFacts from . import SharedUtils @@ -27,73 +29,51 @@ class MlagMixin: @cached_property def mlag(self: SharedUtils) -> bool: - return ( - get(self.node_type_key_data, "mlag_support", default=False) is True - and get(self.switch_data_combined, "mlag", default=True) is True - and len(self.switch_data_node_group_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.""" - return get(self.switch_data, "group") - - @cached_property - def mlag_ibgp_origin_incomplete(self: SharedUtils) -> bool: - return get(self.switch_data_combined, "mlag_ibgp_origin_incomplete", default=True) - - @cached_property - def mlag_peer_vlan(self: SharedUtils) -> int: - return get(self.switch_data_combined, "mlag_peer_vlan", default=4094) + if self.node_group_config is not None: + return self.node_group_config.group + return None @cached_property def mlag_interfaces(self: SharedUtils) -> list: - return range_expand( - default( - get(self.switch_data_combined, "mlag_interfaces"), - get(self.cv_topology_config, "mlag_interfaces"), - get(self.default_interfaces, "mlag_interfaces"), - [], - ), - ) - - @cached_property - def mlag_interfaces_speed(self: SharedUtils) -> str | None: - return get(self.switch_data_combined, "mlag_interfaces_speed") - - @cached_property - def mlag_peer_address_family(self: SharedUtils) -> str: - return get(self.switch_data_combined, "mlag_peer_address_family", default="ipv4") + return range_expand(self.node_config.mlag_interfaces or get(self.cv_topology_config, "mlag_interfaces") or self.default_interfaces.mlag_interfaces) @cached_property def mlag_peer_ipv4_pool(self: SharedUtils) -> str: - return get(self.switch_data_combined, "mlag_peer_ipv4_pool", required=True) + if not self.node_config.mlag_peer_ipv4_pool: + msg = "mlag_peer_ipv4_pool" + raise AristaAvdMissingVariableError(msg) + return self.node_config.mlag_peer_ipv4_pool @cached_property def mlag_peer_ipv6_pool(self: SharedUtils) -> str: - return get(self.switch_data_combined, "mlag_peer_ipv6_pool", required=True) + if not self.node_config.mlag_peer_ipv6_pool: + msg = "mlag_peer_ipv6_pool" + raise AristaAvdMissingVariableError(msg) + return self.node_config.mlag_peer_ipv6_pool @cached_property def mlag_peer_l3_ipv4_pool(self: SharedUtils) -> str: - return get(self.switch_data_combined, "mlag_peer_l3_ipv4_pool", required=True) + if not self.node_config.mlag_peer_l3_ipv4_pool: + msg = "mlag_peer_l3_ipv4_pool" + raise AristaAvdMissingVariableError(msg) + return self.node_config.mlag_peer_l3_ipv4_pool @cached_property - def mlag_role(self: SharedUtils) -> str | None: - if self.mlag: - if self.switch_data_node_group_nodes[0]["name"] == self.hostname: - return "primary" - if self.switch_data_node_group_nodes[1]["name"] == self.hostname: - return "secondary" - msg = "Unable to detect MLAG role" - raise AristaAvdError(msg) + def mlag_role(self: SharedUtils) -> Literal["primary", "secondary"] | None: + 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 mlag_peer(self: SharedUtils) -> str: - if self.mlag_role == "primary": - return self.switch_data_node_group_nodes[1]["name"] - if self.mlag_role == "secondary": - return self.switch_data_node_group_nodes[0]["name"] + 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) @@ -104,8 +84,8 @@ def mlag_l3(self: SharedUtils) -> bool: @cached_property def mlag_peer_l3_vlan(self: SharedUtils) -> int | None: if self.mlag_l3: - mlag_peer_vlan = self.mlag_peer_vlan - mlag_peer_l3_vlan = get(self.switch_data_combined, "mlag_peer_l3_vlan", default=4093) + mlag_peer_vlan = self.node_config.mlag_peer_vlan + mlag_peer_l3_vlan = self.node_config.mlag_peer_l3_vlan if mlag_peer_l3_vlan not in [None, False, mlag_peer_vlan]: return mlag_peer_l3_vlan return None @@ -183,7 +163,7 @@ def mlag_port_channel_id(self: SharedUtils) -> int: msg = f"'mlag_interfaces' not set on '{self.hostname}." raise AristaAvdInvalidInputsError(msg) default_mlag_port_channel_id = int("".join(findall(r"\d", self.mlag_interfaces[0]))) - return get(self.switch_data_combined, "mlag_port_channel_id", default_mlag_port_channel_id) + return default(self.node_config.mlag_port_channel_id, default_mlag_port_channel_id) @cached_property def mlag_peer_port_channel_id(self: SharedUtils) -> int: @@ -193,10 +173,6 @@ def mlag_peer_port_channel_id(self: SharedUtils) -> int: def mlag_peer_interfaces(self: SharedUtils) -> list: return get(self.mlag_peer_facts, "mlag_interfaces", default=self.mlag_interfaces) - @cached_property - def mlag_peer_vlan_structured_config(self: SharedUtils) -> dict | None: - return get(self.switch_data_combined, "mlag_peer_vlan_structured_config") - @cached_property def mlag_ibgp_ip(self: SharedUtils) -> str: if self.mlag_l3_ip is not None: @@ -210,7 +186,3 @@ def mlag_peer_ibgp_ip(self: SharedUtils) -> str: return self.mlag_peer_l3_ip return self.mlag_peer_ip - - @cached_property - def mlag_ibgp_peering_vrfs_base_vlan(self: SharedUtils) -> int: - return int(get(self.hostvars, "mlag_ibgp_peering_vrfs.base_vlan", default=3000)) diff --git a/python-avd/pyavd/_eos_designs/shared_utils/node_config.py b/python-avd/pyavd/_eos_designs/shared_utils/node_config.py new file mode 100644 index 00000000000..56f4396ed85 --- /dev/null +++ b/python-avd/pyavd/_eos_designs/shared_utils/node_config.py @@ -0,0 +1,99 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from __future__ import annotations + +from functools import cached_property +from typing import TYPE_CHECKING + +from pyavd._eos_designs.schema import EosDesigns +from pyavd._errors import AristaAvdInvalidInputsError + +if TYPE_CHECKING: + from . import SharedUtils + + +class NodeConfigMixin: + """ + Mixin Class providing a subset of SharedUtils. + + Class should only be used as Mixin to the SharedUtils class. + Using type-hint on self to get proper type-hints on attributes across all Mixins. + """ + + @cached_property + 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: + return self.inputs._dynamic_keys.custom_node_types[node_type_key].value._cast_as(EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes) + + if node_type_key in self.inputs._dynamic_keys.node_types: + return self.inputs._dynamic_keys.node_types[node_type_key].value + + msg = f"'type' is set to '{self.type}', for which node configs should use the key '{node_type_key}'. '{node_type_key}' was not found." + raise AristaAvdInvalidInputsError(msg) + + @cached_property + def node_group_config(self: SharedUtils) -> 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 None + + @cached_property + def node_config(self: SharedUtils) -> EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem: + """ + NodesItem object containing the fully inherited node config. + + Vars are inherited like: + .defaults -> + .node_groups.[] -> + .node_groups.[].nodes.[] -> + .nodes.[] + """ + node_config = ( + self.node_type_config.nodes[self.hostname] + if self.hostname in self.node_type_config.nodes + else EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem() + ) + + if self.node_group_config is not None: + node_config._deepinherit( + self.node_group_config.nodes[self.hostname]._cast_as(EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem, ignore_extra_keys=True) + ) + node_config._deepinherit(self.node_group_config._cast_as(EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem, ignore_extra_keys=True)) + + node_config._deepinherit( + self.node_type_config.defaults._cast_as(EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem, ignore_extra_keys=True) + ) + + return node_config + + @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] diff --git a/python-avd/pyavd/_eos_designs/shared_utils/node_type.py b/python-avd/pyavd/_eos_designs/shared_utils/node_type.py index 382774f821e..9870b420e49 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/node_type.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/node_type.py @@ -5,10 +5,10 @@ from functools import cached_property from re import search -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Literal from pyavd._errors import AristaAvdInvalidInputsError -from pyavd._utils import get +from pyavd._utils import default if TYPE_CHECKING: from . import SharedUtils @@ -25,7 +25,7 @@ class NodeTypeMixin: @cached_property def type(self: SharedUtils) -> str: """Type fact set based on type variable.""" - if (node_type := get(self.hostvars, "type")) is not None: + if (node_type := self.inputs.type) is not None: return node_type if self.default_node_type: return self.default_node_type @@ -36,20 +36,13 @@ def type(self: SharedUtils) -> str: @cached_property def default_node_type(self: SharedUtils) -> str | None: """default_node_type set based on hostname, returning first node type matching a regex in default_node_types.""" - default_node_types = get(self.hostvars, "default_node_types", default=[]) - - for default_node_type in default_node_types: - for hostname_regex in default_node_type["match_hostnames"]: + for default_node_type in self.inputs.default_node_types: + for hostname_regex in default_node_type.match_hostnames: if search(f"^{hostname_regex}$", self.hostname): - return default_node_type["node_type"] + return default_node_type.node_type return None - @cached_property - def cvp_tag_topology_hint_type(self: SharedUtils) -> str: - """topology_tag_type set based on node_type_keys..cvp_tags.topology_hint_type.""" - return get(self.node_type_key_data, "cvp_tags.topology_hint_type", default="endpoint") - @cached_property def connected_endpoints(self: SharedUtils) -> bool: """ @@ -58,7 +51,7 @@ def connected_endpoints(self: SharedUtils) -> bool: connected_endpoints set based on node_type_keys..connected_endpoints. """ - return get(self.node_type_key_data, "connected_endpoints", default=False) + return self.node_type_key_data.connected_endpoints @cached_property def underlay_router(self: SharedUtils) -> bool: @@ -68,17 +61,16 @@ def underlay_router(self: SharedUtils) -> bool: underlay_router set based on node_type_keys..underlay_router. """ - return get(self.node_type_key_data, "underlay_router", default=True) + return self.node_type_key_data.underlay_router @cached_property - def uplink_type(self: SharedUtils) -> str: + def uplink_type(self: SharedUtils) -> Literal["p2p", "port-channel", "p2p-vrfs", "lan"]: """ Uplink type. uplink_type set based on .nodes.[].uplink_type and node_type_keys..uplink_type. """ - default_uplink_type = get(self.node_type_key_data, "uplink_type", default="p2p") - return get(self.switch_data_combined, "uplink_type", default=default_uplink_type) + return default(self.node_config.uplink_type, self.node_type_key_data.uplink_type) @cached_property def network_services_l1(self: SharedUtils) -> bool: @@ -87,7 +79,7 @@ def network_services_l1(self: SharedUtils) -> bool: network_services_l1 set based on node_type_keys..network_services.l1. """ - return get(self.node_type_key_data, "network_services.l1", default=False) + return self.node_type_key_data.network_services.l1 @cached_property def network_services_l2(self: SharedUtils) -> bool: @@ -96,7 +88,7 @@ def network_services_l2(self: SharedUtils) -> bool: network_services_l2 set based on node_type_keys..network_services.l2. """ - return get(self.node_type_key_data, "network_services.l2", default=False) + return self.node_type_key_data.network_services.l2 @cached_property def network_services_l3(self: SharedUtils) -> bool: @@ -107,9 +99,9 @@ def network_services_l3(self: SharedUtils) -> bool: and . | nodes.<> >.evpn_services_l2_only. """ # network_services_l3 override based on evpn_services_l2_only - if self.vtep is True and get(self.switch_data_combined, "evpn_services_l2_only") is True: + if self.vtep and self.node_config.evpn_services_l2_only: return False - return get(self.node_type_key_data, "network_services.l3", default=False) + return self.node_type_key_data.network_services.l3 @cached_property def network_services_l2_as_subint(self: SharedUtils) -> bool: @@ -124,7 +116,7 @@ def network_services_l2_as_subint(self: SharedUtils) -> bool: @cached_property def any_network_services(self: SharedUtils) -> bool: """Returns True if either L1, L2 or L3 network_services are enabled.""" - return self.network_services_l1 is True or self.network_services_l2 is True or self.network_services_l3 is True + return self.network_services_l1 or self.network_services_l2 or self.network_services_l3 @cached_property def mpls_lsr(self: SharedUtils) -> bool: @@ -134,7 +126,7 @@ def mpls_lsr(self: SharedUtils) -> bool: mpls_lsr set based on node_type_keys..mpls_lsr. """ - return get(self.node_type_key_data, "mpls_lsr", default=False) + return self.node_type_key_data.mpls_lsr @cached_property def vtep(self: SharedUtils) -> bool: @@ -145,5 +137,4 @@ def vtep(self: SharedUtils) -> bool: .nodes.[].vtep and node_type_keys..vtep. """ - default_vtep = get(self.node_type_key_data, "vtep") - return get(self.switch_data_combined, "vtep", default=default_vtep) is True + return default(self.node_config.vtep, self.node_type_key_data.vtep) diff --git a/python-avd/pyavd/_eos_designs/shared_utils/node_type_keys.py b/python-avd/pyavd/_eos_designs/shared_utils/node_type_keys.py index 29dda7276e6..b537c334c8f 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/node_type_keys.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/node_type_keys.py @@ -6,8 +6,9 @@ from functools import cached_property from typing import TYPE_CHECKING +from pyavd._eos_designs.schema import EosDesigns from pyavd._errors import AristaAvdInvalidInputsError -from pyavd._utils import get, get_item, replace_or_append_item +from pyavd._utils import get, get_item if TYPE_CHECKING: from . import SharedUtils @@ -191,27 +192,19 @@ class NodeTypeKeysMixin: """ @cached_property - def node_type_keys(self: SharedUtils) -> list: - """NOTE: This method is called _before_ any schema validation, since we need to resolve node_type_keys dynamically.""" - design_type = get(self.hostvars, "design.type", default="l3ls-evpn") - default_node_type_keys_for_our_design = get(DEFAULT_NODE_TYPE_KEYS, design_type) - - # Using list() to force a copy of node_type_keys so we don't modify the default when we apply custom_node_type_keys - node_type_keys = list(get(self.hostvars, "node_type_keys", default=default_node_type_keys_for_our_design)) - custom_node_type_keys = get(self.hostvars, "custom_node_type_keys", default=[]) - - for node_type_key in custom_node_type_keys: - replace_or_append_item(node_type_keys, "key", node_type_key) - - return node_type_keys - - @cached_property - def node_type_key_data(self: SharedUtils) -> dict: + def node_type_key_data(self: SharedUtils) -> EosDesigns.NodeTypeKeysItem: """node_type_key_data containing settings for this node_type.""" - for node_type_key in self.node_type_keys: - if node_type_key["type"] == self.type: + for node_type_key in self.inputs.custom_node_type_keys: + if node_type_key.type == self.type: + return node_type_key._cast_as(EosDesigns.NodeTypeKeysItem) + + design_type = self.inputs.design.type + default_node_type_keys_for_our_design = EosDesigns.NodeTypeKeys._from_list(get(DEFAULT_NODE_TYPE_KEYS, design_type, default=[])) + node_type_keys = self.inputs.node_type_keys or default_node_type_keys_for_our_design + for node_type_key in node_type_keys: + if node_type_key.type == self.type: return node_type_key # Not found - msg = f"node_type_keys.[type=={self.type}]" + msg = f"Could not find the given type '{self.type}' in node_type_keys or custom_node_type_keys." raise AristaAvdInvalidInputsError(msg) diff --git a/python-avd/pyavd/_eos_designs/shared_utils/overlay.py b/python-avd/pyavd/_eos_designs/shared_utils/overlay.py index 2f860e33503..64c84fc79ee 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/overlay.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/overlay.py @@ -9,7 +9,7 @@ from typing import TYPE_CHECKING from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError -from pyavd._utils import get +from pyavd._utils import default if TYPE_CHECKING: from . import SharedUtils @@ -27,55 +27,32 @@ class OverlayMixin: def vtep_loopback(self: SharedUtils) -> str: """The default is Loopback1 except for WAN devices where the default is Dps1.""" default_vtep_loopback = "Dps1" if self.is_wan_router else "Loopback1" - return get(self.switch_data_combined, "vtep_loopback", default=default_vtep_loopback) + return default(self.node_config.vtep_loopback, default_vtep_loopback) @cached_property def evpn_role(self: SharedUtils) -> str | None: - if self.underlay_router is True: - default_evpn_role = get(self.node_type_key_data, "default_evpn_role", default="none") - return get(self.switch_data_combined, "evpn_role", default=default_evpn_role) + if self.underlay_router: + default_evpn_role = self.node_type_key_data.default_evpn_role + return default(self.node_config.evpn_role, default_evpn_role) return None @cached_property def mpls_overlay_role(self: SharedUtils) -> str | None: - if self.underlay_router is True: - default_mpls_overlay_role = get(self.node_type_key_data, "default_mpls_overlay_role", default="none") - return get(self.switch_data_combined, "mpls_overlay_role", default=default_mpls_overlay_role) + if self.underlay_router: + default_mpls_overlay_role = self.node_type_key_data.default_mpls_overlay_role + return default(self.node_config.mpls_overlay_role, default_mpls_overlay_role) return None - @cached_property - def overlay_rd_type(self: SharedUtils) -> dict: - overlay_rd_type = get(self.hostvars, "overlay_rd_type", default={}) - admin_subfield = get(overlay_rd_type, "admin_subfield", default="router_id") - admin_subfield_offset = int(get(overlay_rd_type, "admin_subfield_offset", default=0)) - return { - "admin_subfield": admin_subfield, - "admin_subfield_offset": admin_subfield_offset, - "vrf_admin_subfield": get(overlay_rd_type, "vrf_admin_subfield", default=admin_subfield), - "vrf_admin_subfield_offset": int(get(overlay_rd_type, "vrf_admin_subfield_offset", default=admin_subfield_offset)), - "vlan_assigned_number_subfield": get(overlay_rd_type, "vlan_assigned_number_subfield", default="mac_vrf_id"), - } - - @cached_property - def overlay_rt_type(self: SharedUtils) -> dict: - overlay_rt_type = get(self.hostvars, "overlay_rt_type", default={}) - admin_subfield = get(overlay_rt_type, "admin_subfield", default="vrf_id") - return { - "admin_subfield": admin_subfield, - "vrf_admin_subfield": get(overlay_rt_type, "vrf_admin_subfield", default=admin_subfield), - "vlan_assigned_number_subfield": get(overlay_rt_type, "vlan_assigned_number_subfield", default="mac_vrf_id"), - } - @cached_property def overlay_rd_type_admin_subfield(self: SharedUtils) -> str: - admin_subfield = self.overlay_rd_type["admin_subfield"] - admin_subfield_offset = self.overlay_rd_type["admin_subfield_offset"] + admin_subfield = self.inputs.overlay_rd_type.admin_subfield + admin_subfield_offset = self.inputs.overlay_rd_type.admin_subfield_offset return self.get_rd_admin_subfield_value(admin_subfield, admin_subfield_offset) @cached_property def overlay_rd_type_vrf_admin_subfield(self: SharedUtils) -> str: - vrf_admin_subfield = self.overlay_rd_type["vrf_admin_subfield"] - vrf_admin_subfield_offset = self.overlay_rd_type["vrf_admin_subfield_offset"] + vrf_admin_subfield: str = default(self.inputs.overlay_rd_type.vrf_admin_subfield, self.inputs.overlay_rd_type.admin_subfield) + vrf_admin_subfield_offset: int = default(self.inputs.overlay_rd_type.vrf_admin_subfield_offset, self.inputs.overlay_rd_type.admin_subfield_offset) return self.get_rd_admin_subfield_value(vrf_admin_subfield, vrf_admin_subfield_offset) def get_rd_admin_subfield_value(self: SharedUtils, admin_subfield: str, admin_subfield_offset: int) -> str: @@ -104,32 +81,18 @@ def get_rd_admin_subfield_value(self: SharedUtils, admin_subfield: str, admin_su return admin_subfield - @cached_property - def evpn_gateway_vxlan_l2(self: SharedUtils) -> bool: - return get(self.switch_data_combined, "evpn_gateway.evpn_l2.enabled", default=False) - - @cached_property - def evpn_gateway_vxlan_l3(self: SharedUtils) -> bool: - return get(self.switch_data_combined, "evpn_gateway.evpn_l3.enabled", default=False) - - @cached_property - def evpn_gateway_vxlan_l3_inter_domain(self: SharedUtils) -> bool: - return get(self.switch_data_combined, "evpn_gateway.evpn_l3.inter_domain", default=True) - @cached_property def overlay_routing_protocol_address_family(self: SharedUtils) -> str: - overlay_routing_protocol_address_family = get(self.hostvars, "overlay_routing_protocol_address_family", default="ipv4") - if overlay_routing_protocol_address_family == "ipv6" and not (self.underlay_ipv6 is True and self.underlay_rfc5549): + overlay_routing_protocol_address_family = self.inputs.overlay_routing_protocol_address_family + if overlay_routing_protocol_address_family == "ipv6" and not (self.underlay_ipv6 is True and self.inputs.underlay_rfc5549): msg = "'overlay_routing_protocol_address_family: ipv6' is only supported in combination with 'underlay_ipv6: True' and 'underlay_rfc5549: True'" - raise AristaAvdError( - msg, - ) + raise AristaAvdError(msg) return overlay_routing_protocol_address_family @cached_property def evpn_encapsulation(self: SharedUtils) -> str: """EVPN encapsulation based on fabric_evpn_encapsulation and node default_evpn_encapsulation.""" - return get(self.hostvars, "fabric_evpn_encapsulation", default=get(self.node_type_key_data, "default_evpn_encapsulation", default="vxlan")) + return default(self.inputs.fabric_evpn_encapsulation, self.node_type_key_data.default_evpn_encapsulation) @cached_property def evpn_soo(self: SharedUtils) -> str: @@ -146,13 +109,19 @@ def evpn_soo(self: SharedUtils) -> str: # for Pathfinder, no HA, no Site ID if not self.is_cv_pathfinder_client: return f"{self.router_id}:0" + + if self.wan_site is None: + # Should never happen but just in case. + msg = "Could not find 'cv_pathfinder_site' so it is not possible to generate evpn_soo." + raise AristaAvdInvalidInputsError(msg) + if not self.wan_ha: - return f"{self.router_id}:{self.wan_site['id']}" + return f"{self.router_id}:{self.wan_site.id}" if self.is_first_ha_peer: - return f"{self.router_id}:{self.wan_site['id']}" + return f"{self.router_id}:{self.wan_site.id}" peer_fact = self.get_peer_facts(self.wan_ha_peer, required=True) - return f"{peer_fact['router_id']}:{self.wan_site['id']}" + return f"{peer_fact['router_id']}:{self.wan_site.id}" if self.overlay_vtep: return f"{self.vtep_ip}:1" @@ -177,7 +146,7 @@ def overlay_mpls(self: SharedUtils) -> bool: @cached_property def overlay_ipvpn_gateway(self: SharedUtils) -> bool: # Set overlay_ipvpn_gateway to trigger ipvpn interworking configuration. - return self.overlay_evpn and get(self.switch_data_combined, "ipvpn_gateway.enabled", default=False) + return self.overlay_evpn and self.node_config.ipvpn_gateway.enabled @cached_property def overlay_ler(self: SharedUtils) -> bool: @@ -201,7 +170,7 @@ def overlay_vpn_ipv4(self: SharedUtils) -> bool: return False return (self.overlay_routing_protocol == "ibgp" and "vpn-ipv4" in self.overlay_address_families) or ( - "vpn-ipv4" in get(self.switch_data_combined, "ipvpn_gateway.address_families", default=["vpn-ipv4"]) and self.overlay_ipvpn_gateway + "vpn-ipv4" in self.node_config.ipvpn_gateway.address_families and self.overlay_ipvpn_gateway ) @cached_property @@ -211,7 +180,7 @@ def overlay_vpn_ipv6(self: SharedUtils) -> bool: return False return (self.overlay_routing_protocol == "ibgp" and "vpn-ipv6" in self.overlay_address_families) or ( - "vpn-ipv6" in get(self.switch_data_combined, "ipvpn_gateway.address_families", default=["vpn-ipv4"]) and self.overlay_ipvpn_gateway + "vpn-ipv6" in self.node_config.ipvpn_gateway.address_families and self.overlay_ipvpn_gateway ) @cached_property @@ -235,7 +204,7 @@ def overlay_her(self: SharedUtils) -> bool: @cached_property def overlay_dpath(self: SharedUtils) -> bool: # Set dpath based on ipvpn_gateway parameters - return self.overlay_ipvpn_gateway and get(self.switch_data_combined, "ipvpn_gateway.enable_d_path", default=True) + return self.overlay_ipvpn_gateway and self.node_config.ipvpn_gateway.enable_d_path @cached_property def overlay_evpn_vxlan(self: SharedUtils) -> bool: @@ -244,7 +213,3 @@ def overlay_evpn_vxlan(self: SharedUtils) -> bool: @cached_property def overlay_evpn_mpls(self: SharedUtils) -> bool: return self.overlay_evpn and self.evpn_encapsulation == "mpls" - - @cached_property - def overlay_mlag_rfc5549(self: SharedUtils) -> bool: - return get(self.hostvars, "overlay_mlag_rfc5549") is True diff --git a/python-avd/pyavd/_eos_designs/shared_utils/platform.py b/python-avd/pyavd/_eos_designs/shared_utils/platform.py index 627c9523879..c9c6999d672 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/platform.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/platform.py @@ -7,7 +7,8 @@ from re import search from typing import TYPE_CHECKING -from pyavd._utils import default, get +from pyavd._eos_designs.schema import EosDesigns +from pyavd._utils import default if TYPE_CHECKING: from . import SharedUtils @@ -23,65 +24,44 @@ class PlatformMixin: @cached_property def platform(self: SharedUtils) -> str | None: - return get(self.switch_data_combined, "platform", default=self.cv_topology_platform) + return default(self.node_config.platform, self.cv_topology_platform) @cached_property - def platform_settings(self: SharedUtils) -> dict: - custom_platform_settings = get(self.hostvars, "custom_platform_settings", default=[]) - - # Reading default value from schema - default_platform_settings = self.schema.get_default_value(["platform_settings"]) - platform_settings = custom_platform_settings + get(self.hostvars, "platform_settings", default=default_platform_settings) - + def platform_settings(self: SharedUtils) -> EosDesigns.PlatformSettingsItem | EosDesigns.CustomPlatformSettingsItem: # First look for a matching platform setting specifying our platform - for platform_setting in platform_settings: - if self.platform in platform_setting.get("platforms", []): - return platform_setting + if self.platform is not None: + for platform_setting in self.inputs.custom_platform_settings: + if self.platform in platform_setting.platforms: + return platform_setting + for platform_setting in self.inputs.platform_settings: + if self.platform in platform_setting.platforms: + return platform_setting # If not found, then look for a default platform setting - for platform_setting in platform_settings: - if "default" in platform_setting.get("platforms", []): + for platform_setting in self.inputs.custom_platform_settings: + if "default" in platform_setting.platforms: + return platform_setting + for platform_setting in self.inputs.platform_settings: + if "default" in platform_setting.platforms: return platform_setting - return {} + return EosDesigns.PlatformSettingsItem() @cached_property - def default_interfaces(self: SharedUtils) -> dict: + def default_interfaces(self: SharedUtils) -> EosDesigns.DefaultInterfacesItem: """default_interfaces set based on default_interfaces.""" - default_interfaces = get(self.hostvars, "default_interfaces", default=[]) - - device_platform = default(self.platform, "default") + device_platform = self.platform or "default" # First look for a matching default interface set that matches our platform and type - for default_interface in default_interfaces: - for platform in default_interface.get("platforms", []): - if search(f"^{platform}$", device_platform) and self.type in default_interface.get("types", []): + for default_interface in self.inputs.default_interfaces: + for platform in default_interface.platforms: + if search(f"^{platform}$", device_platform) and self.type in default_interface.types: return default_interface # If not found, then look for a default default_interface that matches our type - for default_interface in default_interfaces: - for platform in default_interface.get("platforms", []): - if search(f"^{platform}$", "default") and self.type in default_interface.get("types", []): + for default_interface in self.inputs.default_interfaces: + for platform in default_interface.platforms: + if search(f"^{platform}$", "default") and self.type in default_interface.types: return default_interface - return {} - - @cached_property - def platform_settings_feature_support_interface_storm_control(self) -> bool: - return get(self.platform_settings, "feature_support.interface_storm_control", default=True) is True - - @cached_property - def platform_settings_feature_support_queue_monitor_length_notify(self) -> bool: - return get(self.platform_settings, "feature_support.queue_monitor_length_notify", default=True) is True - - @cached_property - def platform_settings_feature_support_poe(self) -> bool: - return get(self.platform_settings, "feature_support.poe", default=False) is True - - @cached_property - def platform_settings_feature_support_per_interface_mtu(self) -> bool: - return get(self.platform_settings, "feature_support.per_interface_mtu", default=True) is True - - @cached_property - def platform_settings_p2p_uplinks_mtu(self) -> int | None: - return get(self.platform_settings, "p2p_uplinks_mtu") + return EosDesigns.DefaultInterfacesItem() diff --git a/python-avd/pyavd/_eos_designs/shared_utils/ptp.py b/python-avd/pyavd/_eos_designs/shared_utils/ptp.py index 77fde6da48b..b48cdd8fd78 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/ptp.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/ptp.py @@ -6,9 +6,12 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import get, get_item +from pyavd._errors import AristaAvdInvalidInputsError +from pyavd._utils import default if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + from . import SharedUtils @@ -22,25 +25,18 @@ class PtpMixin: @cached_property def ptp_enabled(self: SharedUtils) -> bool: - default_ptp_enabled = get(self.hostvars, "ptp_settings.enabled") - return get(self.switch_data_combined, "ptp.enabled", default=default_ptp_enabled) is True - - @cached_property - def ptp_mlag(self: SharedUtils) -> bool: - return get(self.switch_data_combined, "ptp.mlag") is True + default_ptp_enabled = self.inputs.ptp_settings.enabled + return bool(default(self.node_config.ptp.enabled, default_ptp_enabled)) @cached_property def ptp_profile_name(self: SharedUtils) -> str: - default_ptp_profile = get(self.hostvars, "ptp_settings.profile", default="aes67-r16-2016") - return get(self.switch_data_combined, "ptp.profile", default=default_ptp_profile) + default_ptp_profile = self.inputs.ptp_settings.profile + return self.node_config.ptp.profile or default_ptp_profile @cached_property - def ptp_profile(self: SharedUtils) -> dict: - msg = f"PTP Profile '{self.ptp_profile_name}' referenced under `ptp.profile` node variables does not exist in `ptp_profiles`." - return get_item(self.ptp_profiles, "profile", self.ptp_profile_name, required=True, custom_error_msg=msg) + def ptp_profile(self: SharedUtils) -> EosDesigns.PtpProfilesItem: + if self.ptp_profile_name not in self.inputs.ptp_profiles: + msg = f"PTP Profile '{self.ptp_profile_name}' referenced under `ptp.profile` node variables does not exist in `ptp_profiles`." + raise AristaAvdInvalidInputsError(msg) - @cached_property - def ptp_profiles(self: SharedUtils) -> list: - """Return ptp_profiles.""" - default_ptp_profiles = self.schema.get_default_value(["ptp_profiles"]) - return get(self.hostvars, "ptp_profiles", default=default_ptp_profiles) + return self.inputs.ptp_profiles[self.ptp_profile_name] diff --git a/python-avd/pyavd/_eos_designs/shared_utils/routing.py b/python-avd/pyavd/_eos_designs/shared_utils/routing.py index 03bfdcc8c57..8fb3d9f523a 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/routing.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/routing.py @@ -6,8 +6,7 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError -from pyavd._utils import get +from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError, AristaAvdMissingVariableError from pyavd.j2filters import range_expand if TYPE_CHECKING: @@ -24,19 +23,19 @@ class RoutingMixin: @cached_property def underlay_routing_protocol(self: SharedUtils) -> str: - default_underlay_routing_protocol = get(self.node_type_key_data, "default_underlay_routing_protocol", default="ebgp") - return str(get(self.hostvars, "underlay_routing_protocol", default=default_underlay_routing_protocol)).lower() + default_underlay_routing_protocol = self.node_type_key_data.default_underlay_routing_protocol + return (self.inputs.underlay_routing_protocol or default_underlay_routing_protocol).lower() @cached_property def overlay_routing_protocol(self: SharedUtils) -> str: - default_overlay_routing_protocol = get(self.node_type_key_data, "default_overlay_routing_protocol", default="ebgp") - return str(get(self.hostvars, "overlay_routing_protocol", default=default_overlay_routing_protocol)).lower() + default_overlay_routing_protocol = self.node_type_key_data.default_overlay_routing_protocol + return (self.inputs.overlay_routing_protocol or default_overlay_routing_protocol).lower() @cached_property - def overlay_address_families(self: SharedUtils) -> list: + def overlay_address_families(self: SharedUtils) -> list[str]: if self.overlay_routing_protocol in ["ebgp", "ibgp"]: - default_overlay_address_families = get(self.node_type_key_data, "default_overlay_address_families", ["evpn"]) - return get(self.switch_data_combined, "overlay_address_families", default=default_overlay_address_families) + default_overlay_address_families = self.node_type_key_data.default_overlay_address_families + return self.node_config.overlay_address_families._as_list() or default_overlay_address_families._as_list() return [] @cached_property @@ -75,7 +74,7 @@ def ipv6_router_id(self: SharedUtils) -> str | None: def isis_instance_name(self: SharedUtils) -> str | None: if self.underlay_router and self.underlay_routing_protocol in ["isis", "isis-ldp", "isis-sr", "isis-sr-ldp"]: default_isis_instance_name = "CORE" if self.mpls_lsr else "EVPN_UNDERLAY" - return get(self.hostvars, "underlay_isis_instance_name", default=default_isis_instance_name) + return self.inputs.underlay_isis_instance_name or default_isis_instance_name return None @cached_property @@ -92,26 +91,27 @@ def bgp_as(self: SharedUtils) -> str | None: at the defaults, node_group or node level). - Lower level definitions override higher level definitions as is standard with AVD. """ - if self.bgp: - if get(self.hostvars, "bgp_as") is not None: - return str(get(self.hostvars, "bgp_as")) - - bgp_as_range_expanded = range_expand(str(get(self.switch_data_combined, "bgp_as", required=True))) - try: - if len(bgp_as_range_expanded) == 1: - return bgp_as_range_expanded[0] - if self.mlag: - return bgp_as_range_expanded[self.mlag_switch_ids["primary"] - 1] - - if self.id is None: - msg = f"'id' is not set on '{self.hostname}' and is required when expanding 'bgp_as'" - raise AristaAvdInvalidInputsError(msg) - return bgp_as_range_expanded[self.id - 1] - except IndexError as exc: - msg = f"Unable to allocate BGP AS: bgp_as range is too small ({len(bgp_as_range_expanded)}) for the id of the device" - raise AristaAvdError(msg) from exc - return None - - @cached_property - def always_configure_ip_routing(self: SharedUtils) -> bool: - return get(self.switch_data_combined, "always_configure_ip_routing") + if not self.bgp: + return None + + if self.inputs.bgp_as: + return self.inputs.bgp_as + + if self.node_config.bgp_as is None: + msg = "bgp_as" + raise AristaAvdMissingVariableError(msg) + + bgp_as_range_expanded = range_expand(self.node_config.bgp_as) + try: + if len(bgp_as_range_expanded) == 1: + return bgp_as_range_expanded[0] + if self.mlag_switch_ids: + return bgp_as_range_expanded[self.mlag_switch_ids["primary"] - 1] + + if self.id is None: + msg = f"'id' is not set on '{self.hostname}' and is required when expanding 'bgp_as'" + raise AristaAvdInvalidInputsError(msg) + return bgp_as_range_expanded[self.id - 1] + except IndexError as exc: + msg = f"Unable to allocate BGP AS: bgp_as range is too small ({len(bgp_as_range_expanded)}) for the id of the device" + raise AristaAvdError(msg) from exc diff --git a/python-avd/pyavd/_eos_designs/shared_utils/switch_data.py b/python-avd/pyavd/_eos_designs/shared_utils/switch_data.py deleted file mode 100644 index 79d3d6670fb..00000000000 --- a/python-avd/pyavd/_eos_designs/shared_utils/switch_data.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (c) 2023-2024 Arista Networks, Inc. -# Use of this source code is governed by the Apache License 2.0 -# that can be found in the LICENSE file. -from __future__ import annotations - -from functools import cached_property -from typing import TYPE_CHECKING - -from pyavd._utils import get, merge - -if TYPE_CHECKING: - from . import SharedUtils - - -class SwitchDataMixin: - """ - Mixin Class providing a subset of SharedUtils. - - Class should only be used as Mixin to the SharedUtils class. - Using type-hint on self to get proper type-hints on attributes across all Mixins. - """ - - @cached_property - def switch_data(self: SharedUtils) -> dict: - """ - internal _switch_data containing inherited vars from fabric_topology data model. - - Vars are inherited like: - .defaults -> - .node_groups.[] -> - .node_groups.[].nodes.[] -> - .nodes.[] - - Returns: - ------- - dict - node_group : dict - Configuration set at the node_group level - including the "nodes" list. - Empty dict if the node is not defined under a node_group. - group : str - Optional - Name of the matching node_group. Not set if the node is not defined under a node_group. - combined : dict - Combined configuration after inheritance from all levels - """ - switch_data = {"node_group": {}} - node_config = {} - hostname = self.hostname - - node_type_key = self.node_type_key_data["key"] - node_type_config = get(self.hostvars, f"{node_type_key}", required=True) - nodes = node_type_config.get("nodes", []) - - for node in nodes: - if hostname == node["name"]: - node_config = node - break - if not node_config: - node_groups = node_type_config.get("node_groups", []) - for node_group in node_groups: - nodes = node_group.get("nodes", []) - node_group["nodes"] = nodes - for node in nodes: - if hostname == node["name"]: - node_config = node - switch_data["node_group"] = node_group - switch_data["group"] = node_group["group"] - break - if node_config: - break - - # Load defaults - defaults_config = get(node_type_config, "defaults", default={}) - - # Merge node data -> node_group data -> defaults into combined - switch_data["combined"] = merge(defaults_config, switch_data["node_group"], node_config, list_merge="replace", destructive_merge=False) - - return switch_data - - @property - def switch_data_combined(self: SharedUtils) -> dict: - """switch_data_combined containing self._switch_data['combined'] for easier reference.""" - return self.switch_data["combined"] - - @cached_property - def switch_data_node_group_nodes(self: SharedUtils) -> list: - """switch_data_node_group_nodes pointing to self.switch_data['node_group']['nodes'] for easier reference.""" - return get(self.switch_data, "node_group.nodes", default=[]) diff --git a/python-avd/pyavd/_eos_designs/shared_utils/underlay.py b/python-avd/pyavd/_eos_designs/shared_utils/underlay.py index 15422209adb..ec8f4484ec6 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/underlay.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/underlay.py @@ -6,8 +6,6 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import get, get_item - if TYPE_CHECKING: from . import SharedUtils @@ -55,41 +53,27 @@ def underlay_isis(self: SharedUtils) -> bool: @cached_property def underlay_ipv6(self: SharedUtils) -> bool: - return get(self.hostvars, "underlay_ipv6", default=False) and self.underlay_router + return self.inputs.underlay_ipv6 and self.underlay_router @cached_property def underlay_multicast(self: SharedUtils) -> bool: - return get(self.hostvars, "underlay_multicast") and self.underlay_router - - @cached_property - def underlay_multicast_rps(self: SharedUtils) -> list[dict] | None: - if not self.underlay_multicast: - return None - - return get(self.hostvars, "underlay_multicast_rps") - - @cached_property - def underlay_multicast_anycast_rp_mode(self: SharedUtils) -> str: - return get(self.hostvars, "underlay_multicast_anycast_rp.mode", default="pim") + return self.inputs.underlay_multicast and self.underlay_router @cached_property def underlay_multicast_rp_interfaces(self: SharedUtils) -> list[dict] | None: - if self.underlay_multicast_rps is None: + if not self.underlay_multicast or not self.inputs.underlay_multicast_rps: return None underlay_multicast_rp_interfaces = [] - for rp_entry in self.underlay_multicast_rps: - if (nodes := get(rp_entry, "nodes")) is None: - continue - - if (node_entry := get_item(nodes, "name", self.hostname)) is None: + for rp_entry in self.inputs.underlay_multicast_rps: + if self.hostname not in rp_entry.nodes: continue underlay_multicast_rp_interfaces.append( { - "name": f"Loopback{node_entry['loopback_number']}", - "description": get(node_entry, "description", default="PIM RP"), - "ip_address": f"{rp_entry['rp']}/32", + "name": f"Loopback{rp_entry.nodes[self.hostname].loopback_number}", + "description": rp_entry.nodes[self.hostname].description, + "ip_address": f"{rp_entry.rp}/32", }, ) @@ -97,23 +81,3 @@ def underlay_multicast_rp_interfaces(self: SharedUtils) -> list[dict] | None: return underlay_multicast_rp_interfaces return None - - @cached_property - def underlay_filter_redistribute_connected(self: SharedUtils) -> bool: - return get(self.hostvars, "underlay_filter_redistribute_connected", default=True) is True - - @cached_property - def underlay_rfc5549(self: SharedUtils) -> bool: - return get(self.hostvars, "underlay_rfc5549") is True - - @cached_property - def underlay_ospf_process_id(self: SharedUtils) -> int: - return get(self.hostvars, "underlay_ospf_process_id", default=100) - - @cached_property - def underlay_ospf_area(self: SharedUtils) -> str: - return get(self.hostvars, "underlay_ospf_area", default="0.0.0.0") # noqa: S104 - - @cached_property - def underlay_filter_peer_as(self: SharedUtils) -> bool: - return get(self.hostvars, "underlay_filter_peer_as") is True diff --git a/python-avd/pyavd/_eos_designs/shared_utils/utils.py b/python-avd/pyavd/_eos_designs/shared_utils/utils.py index e1064df8f88..f4ce43a2398 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/utils.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/utils.py @@ -6,14 +6,21 @@ from functools import lru_cache from typing import TYPE_CHECKING -from pyavd._errors import AristaAvdError -from pyavd._utils import get, get_item, merge, template_var +from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError +from pyavd._utils import get, template_var if TYPE_CHECKING: + from typing import TypeVar + from pyavd._eos_designs.eos_designs_facts import EosDesignsFacts + from pyavd._eos_designs.schema import EosDesigns from . import SharedUtils + ADAPTER_SETTINGS = TypeVar( + "ADAPTER_SETTINGS", EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem, EosDesigns.NetworkPortsItem + ) + class UtilsMixin: """ @@ -52,20 +59,27 @@ def template_var(self: SharedUtils, template_file: str, template_vars: dict) -> raise AristaAvdError(msg) from e @lru_cache # noqa: B019 - def get_merged_port_profile(self: SharedUtils, profile_name: str, context: str) -> list: + def get_merged_port_profile(self: SharedUtils, profile_name: str, context: str) -> EosDesigns.PortProfilesItem: """Return list of merged "port_profiles" where "parent_profile" has been applied.""" - msg = f"Profile '{profile_name}' applied under '{context}' does not exist in `port_profiles`." - port_profile = get_item(self.port_profiles, "profile", profile_name, required=True, custom_error_msg=msg) - if "parent_profile" in port_profile: - msg = f"Profile '{port_profile['parent_profile']}' applied under port profile '{profile_name}' does not exist in `port_profiles`." - parent_profile = get_item(self.port_profiles, "profile", port_profile["parent_profile"], required=True, custom_error_msg=msg) + if profile_name not in self.inputs.port_profiles: + msg = f"Profile '{profile_name}' applied under '{context}' does not exist in `port_profiles`." + raise AristaAvdInvalidInputsError(msg) + + port_profile = self.inputs.port_profiles[profile_name] + if port_profile.parent_profile: + if port_profile.parent_profile not in self.inputs.port_profiles: + msg = f"Profile '{port_profile.parent_profile}' applied under port profile '{profile_name}' does not exist in `port_profiles`." + raise AristaAvdInvalidInputsError(msg) + + parent_profile = self.inputs.port_profiles[port_profile.parent_profile] + # Notice reuse of the same variable with the merged content. - port_profile = merge(parent_profile, port_profile, list_merge="replace", destructive_merge=False) - port_profile.pop("parent_profile") + port_profile = port_profile._deepinherited(parent_profile) + delattr(port_profile, "parent_profile") return port_profile - def get_merged_adapter_settings(self: SharedUtils, adapter_or_network_port_settings: dict) -> dict: + def get_merged_adapter_settings(self: SharedUtils, adapter_or_network_port_settings: ADAPTER_SETTINGS) -> ADAPTER_SETTINGS: """ Applies port-profiles to the given adapter_or_network_port and returns the combined result. @@ -73,9 +87,14 @@ def get_merged_adapter_settings(self: SharedUtils, adapter_or_network_port_setti adapter_or_network_port_settings: can either be an adapter of a connected endpoint or one item under network_ports. context: a context string for error messages. """ - if (profile_name := adapter_or_network_port_settings.get("profile")) is None: + # Deepcopy to avoid modifying the original. + adapter_or_network_port_settings = adapter_or_network_port_settings._deepcopy() + + if (profile_name := adapter_or_network_port_settings.profile) is None: # No profile to apply return adapter_or_network_port_settings - adapter_profile = self.get_merged_port_profile(profile_name, adapter_or_network_port_settings["context"]) - return merge(adapter_profile, adapter_or_network_port_settings, list_merge="replace", destructive_merge=False) + adapter_profile = self.get_merged_port_profile(profile_name, adapter_or_network_port_settings._context) + profile_as_adapter_or_network_port_settings = adapter_profile._cast_as(type(adapter_or_network_port_settings)) + adapter_or_network_port_settings._deepinherit(profile_as_adapter_or_network_port_settings) + return adapter_or_network_port_settings diff --git a/python-avd/pyavd/_eos_designs/shared_utils/wan.py b/python-avd/pyavd/_eos_designs/shared_utils/wan.py index 2d4d07d6ad8..578cea015f5 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/wan.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/wan.py @@ -7,8 +7,9 @@ from re import findall from typing import TYPE_CHECKING, Literal -from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError -from pyavd._utils import default, get, get_ip_from_ip_prefix, get_item, strip_empties_from_dict +from pyavd._eos_designs.schema import EosDesigns +from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError, AristaAvdMissingVariableError +from pyavd._utils import default, get, get_ip_from_ip_prefix, strip_empties_from_dict from pyavd.j2filters import natural_sort if TYPE_CHECKING: @@ -23,17 +24,13 @@ class WanMixin: Using type-hint on self to get proper type-hints on attributes across all Mixins. """ - @cached_property - def wan_mode(self: SharedUtils) -> str: - return get(self.hostvars, "wan_mode", default="cv-pathfinder") - @cached_property def wan_role(self: SharedUtils) -> str | None: if self.underlay_router is False: return None - default_wan_role = get(self.node_type_key_data, "default_wan_role", default=None) - wan_role = get(self.switch_data_combined, "wan_role", default=default_wan_role) + default_wan_role = self.node_type_key_data.default_wan_role + wan_role = self.node_config.wan_role or default_wan_role if wan_role is not None and self.overlay_routing_protocol != "ibgp": msg = "Only 'ibgp' is supported as 'overlay_routing_protocol' for WAN nodes." raise AristaAvdError(msg) @@ -58,13 +55,11 @@ def is_wan_client(self: SharedUtils) -> bool: return self.wan_role == "client" @cached_property - def wan_listen_ranges(self: SharedUtils) -> list: - return get( - self.bgp_peer_groups["wan_overlay_peers"], - "listen_range_prefixes", - required=True, - org_key="bgp_peer_groups.wan_overlay_peers.listen_range_prefixes", - ) + def wan_listen_ranges(self: SharedUtils) -> EosDesigns.BgpPeerGroups.WanOverlayPeers.ListenRangePrefixes: + if not self.inputs.bgp_peer_groups.wan_overlay_peers.listen_range_prefixes: + msg = "bgp_peer_groups.wan_overlay_peers.listen_range_prefixes" + raise AristaAvdMissingVariableError(msg) + return self.inputs.bgp_peer_groups.wan_overlay_peers.listen_range_prefixes @cached_property def cv_pathfinder_transit_mode(self: SharedUtils) -> Literal["region", "zone"] | None: @@ -72,10 +67,10 @@ def cv_pathfinder_transit_mode(self: SharedUtils) -> Literal["region", "zone"] | if not self.is_cv_pathfinder_client: return None - return get(self.switch_data_combined, "cv_pathfinder_transit_mode") + return self.node_config.cv_pathfinder_transit_mode @cached_property - def wan_interfaces(self: SharedUtils) -> list: + def wan_interfaces(self: SharedUtils) -> EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem.L3Interfaces: """ As a first approach, only interfaces under node config l3_interfaces can be considered as WAN interfaces. @@ -83,20 +78,16 @@ def wan_interfaces(self: SharedUtils) -> list: This also may require a different format for the dictionaries inside the list. """ if not self.is_wan_router: - return [] + return EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem.L3Interfaces() - wan_interfaces = [interface for interface in self.l3_interfaces if get(interface, "wan_carrier") is not None] + wan_interfaces = EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem.L3Interfaces( + [interface for interface in self.l3_interfaces if interface.wan_carrier] + ) if not wan_interfaces: msg = "At least one WAN interface must be configured on a WAN router. Add WAN interfaces under `l3_interfaces` node setting with `wan_carrier` set." - raise AristaAvdError( - msg, - ) + raise AristaAvdError(msg) return wan_interfaces - @cached_property - def wan_carriers(self: SharedUtils) -> list: - return get(self.hostvars, "wan_carriers", required=True) - @cached_property def wan_local_carriers(self: SharedUtils) -> list: """ @@ -111,24 +102,21 @@ def wan_local_carriers(self: SharedUtils) -> list: local_carriers_dict = {} for interface in self.wan_interfaces: - interface_carrier = interface["wan_carrier"] + interface_carrier: str = interface.wan_carrier if interface_carrier not in local_carriers_dict: - local_carriers_dict[interface_carrier] = get_item( - self.wan_carriers, - "name", - interface["wan_carrier"], - required=True, - custom_error_msg=f"WAN carrier {interface['wan_carrier']} is not in the available carriers defined in `wan_carriers`", - ).copy() + if interface_carrier not in self.inputs.wan_carriers: + msg = f"WAN carrier {interface_carrier} is not in the available carriers defined in `wan_carriers`" + raise AristaAvdInvalidInputsError(msg) + local_carriers_dict[interface_carrier] = self.inputs.wan_carriers[interface_carrier]._as_dict(include_default_values=True) local_carriers_dict[interface_carrier]["interfaces"] = [] local_carriers_dict[interface_carrier]["interfaces"].append( strip_empties_from_dict( { - "name": get(interface, "name", required=True), + "name": interface.name, "public_ip": self.get_public_ip_for_wan_interface(interface), - "connected_to_pathfinder": get(interface, "connected_to_pathfinder", default=True), - "wan_circuit_id": get(interface, "wan_circuit_id"), + "connected_to_pathfinder": interface.connected_to_pathfinder, + "wan_circuit_id": interface.wan_circuit_id, }, ), ) @@ -136,19 +124,7 @@ def wan_local_carriers(self: SharedUtils) -> list: return list(local_carriers_dict.values()) @cached_property - def wan_path_groups(self: SharedUtils) -> list: - """ - List of path-groups defined in the top level key `wan_path_groups`. - - Updating default preference for each path-group to 'preferred' if not set. - """ - path_groups = get(self.hostvars, "wan_path_groups", required=True) - for path_group in path_groups: - path_group["default_preference"] = get(path_group, "default_preference", default="preferred") - return path_groups - - @cached_property - def wan_local_path_groups(self: SharedUtils) -> list: + def wan_local_path_groups(self: SharedUtils) -> EosDesigns.WanPathGroups: """ List of path-groups present on this router based on the local carriers. @@ -157,33 +133,29 @@ def wan_local_path_groups(self: SharedUtils) -> list: - name: ... public_ip: ... """ - if not self.is_wan_router: - return [] + local_path_groups = EosDesigns.WanPathGroups() - local_path_groups_dict = {} + if not self.is_wan_router: + return local_path_groups for carrier in self.wan_local_carriers: - path_group_name = get(carrier, "path_group", required=True) - if path_group_name not in local_path_groups_dict: - local_path_groups_dict[path_group_name] = get_item( - self.wan_path_groups, - "name", - path_group_name, - required=True, - custom_error_msg=( - f"WAN path_group {path_group_name} defined for a WAN carrier is not in the available path_groups defined in `wan_path_groups`" - ), - ).copy() - local_path_groups_dict[path_group_name]["interfaces"] = [] + path_group_name: str = get(carrier, "path_group", required=True) + if path_group_name not in local_path_groups: + if path_group_name not in self.inputs.wan_path_groups: + msg = f"WAN path_group {path_group_name} defined for a WAN carrier is not in the available path_groups defined in `wan_path_groups`" + raise AristaAvdInvalidInputsError(msg) - local_path_groups_dict[path_group_name]["interfaces"].extend(carrier["interfaces"]) + local_path_groups[path_group_name] = self.inputs.wan_path_groups[path_group_name]._deepcopy() + local_path_groups[path_group_name]._interfaces = [] - return list(local_path_groups_dict.values()) + local_path_groups[path_group_name]._interfaces.extend(carrier["interfaces"]) + + return local_path_groups @cached_property def wan_local_path_group_names(self: SharedUtils) -> list: """Return a list of wan_local_path_group names.""" - return [path_group["name"] for path_group in self.wan_local_path_groups] + return list(self.wan_local_path_groups.keys()) @cached_property def wan_ha_peer_path_groups(self: SharedUtils) -> list: @@ -198,17 +170,7 @@ def wan_ha_peer_path_group_names(self: SharedUtils) -> list: """Return a list of wan_ha_peer_path_group names.""" return [path_group["name"] for path_group in self.wan_ha_peer_path_groups] - @cached_property - def this_wan_route_server(self: SharedUtils) -> dict: - """ - Returns the instance for this wan_rs found under wan_route_servers. - - Should only be called when the device is actually a wan_rs. - """ - wan_route_servers = get(self.hostvars, "wan_route_servers", default=[]) - return get_item(wan_route_servers, "hostname", self.hostname, default={}) - - def get_public_ip_for_wan_interface(self: SharedUtils, interface: dict) -> str: + def get_public_ip_for_wan_interface(self: SharedUtils, interface: EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem.L3InterfacesItem) -> str: """ Takes a dict which looks like `l3_interface` from node config. @@ -219,100 +181,79 @@ def get_public_ip_for_wan_interface(self: SharedUtils, interface: dict) -> str: If there is no public_ip and if ip_address is "dhcp" we raise an error. """ if not self.is_wan_server: - return default(interface.get("public_ip"), get_ip_from_ip_prefix(interface["ip_address"])) + return default(interface.public_ip, get_ip_from_ip_prefix(interface.ip_address)) - for path_group in self.this_wan_route_server.get("path_groups", []): - if (found_interface := get_item(path_group["interfaces"], "name", interface["name"])) is None: - continue + if self.hostname in self.inputs.wan_route_servers: + for path_group in self.inputs.wan_route_servers[self.hostname].path_groups: + if interface.name not in path_group.interfaces: + continue - if found_interface.get("public_ip") is not None: - return found_interface["public_ip"] + if public_ip := path_group.interfaces[interface.name].public_ip: + return public_ip - if interface.get("public_ip") is not None: - return interface["public_ip"] + if interface.public_ip: + return interface.public_ip - if interface["ip_address"] == "dhcp": + if interface.ip_address == "dhcp": msg = ( - f"The IP address for WAN interface '{interface['name']}' on Route Server '{self.hostname}' is set to 'dhcp'. " + f"The IP address for WAN interface '{interface.name}' on Route Server '{self.hostname}' is set to 'dhcp'. " "Clients need to peer with a static IP which must be set under the 'wan_route_servers.path_groups.interfaces' key." ) - raise AristaAvdError( - msg, - ) + raise AristaAvdError(msg) - return get_ip_from_ip_prefix(interface["ip_address"]) + return get_ip_from_ip_prefix(interface.ip_address) @cached_property - def wan_site(self: SharedUtils) -> dict | None: + def wan_site(self: SharedUtils) -> EosDesigns.CvPathfinderRegionsItem.SitesItem | EosDesigns.CvPathfinderGlobalSitesItem | None: """ WAN site for CV Pathfinder. The site is required for edges, but optional for pathfinders """ - node_defined_site = get( - self.switch_data_combined, - "cv_pathfinder_site", - required=self.is_cv_pathfinder_client, - custom_error_msg="A node variable 'cv_pathfinder_site' must be defined when 'wan_role' is 'client' and 'wan_mode' is 'cv-pathfinder'.", - ) - if node_defined_site is None: + node_defined_site = self.node_config.cv_pathfinder_site + if not node_defined_site and self.is_cv_pathfinder_client: + msg = "A node variable 'cv_pathfinder_site' must be defined when 'wan_role' is 'client' and 'wan_mode' is 'cv-pathfinder'." + raise AristaAvdInvalidInputsError(msg) + + if not node_defined_site: return None # Special case for cv_pathfinders without a region, we find the site details under `cv_pathfinder_global_sites` instead. if self.is_cv_pathfinder_server and self.wan_region is None: - sites = get(self.hostvars, "cv_pathfinder_global_sites", required=True) - site_not_found_error_msg = ( - f"The 'cv_pathfinder_site '{node_defined_site}' defined at the node level could not be found under the 'cv_pathfinder_global_sites' list" - ) - else: - sites = get( - self.wan_region, "sites", required=True, custom_error_msg=f"The CV Pathfinder region '{self.wan_region['name']}' is missing a list of sites." - ) - site_not_found_error_msg = ( - ( - f"The 'cv_pathfinder_site '{node_defined_site}' defined at the node level could not be found under the 'sites' list for the region" - f" '{self.wan_region['name']}'." - ), + if node_defined_site not in self.inputs.cv_pathfinder_global_sites: + msg = f"The 'cv_pathfinder_site '{node_defined_site}' defined at the node level could not be found under the 'cv_pathfinder_global_sites' list" + raise AristaAvdInvalidInputsError(msg) + return self.inputs.cv_pathfinder_global_sites[node_defined_site] + + if self.wan_region is None or node_defined_site not in self.wan_region.sites: + msg = ( + f"The 'cv_pathfinder_site '{node_defined_site}' defined at the node level could not be found under the 'sites' list for the region" + f" '{self.wan_region.name if self.wan_region is not None else '.'}'." ) + raise AristaAvdInvalidInputsError(msg) - return get_item( - sites, - "name", - node_defined_site, - required=True, - custom_error_msg=site_not_found_error_msg, - ) + return self.wan_region.sites[node_defined_site] @cached_property - def wan_region(self: SharedUtils) -> dict | None: + def wan_region(self: SharedUtils) -> EosDesigns.CvPathfinderRegionsItem | None: """ WAN region for CV Pathfinder. The region is required for edges, but optional for pathfinders """ - node_defined_region = get( - self.switch_data_combined, - "cv_pathfinder_region", - required=self.is_cv_pathfinder_client, - custom_error_msg="A node variable 'cv_pathfinder_region' must be defined when 'wan_role' is 'client' and 'wan_mode' is 'cv-pathfinder'.", - ) + node_defined_region = self.node_config.cv_pathfinder_region + if not node_defined_region and self.is_cv_pathfinder_client: + msg = "A node variable 'cv_pathfinder_region' must be defined when 'wan_role' is 'client' and 'wan_mode' is 'cv-pathfinder'." + raise AristaAvdInvalidInputsError(msg) + if node_defined_region is None: return None - regions = get( - self.hostvars, - "cv_pathfinder_regions", - required=True, - custom_error_msg="'cv_pathfinder_regions' key must be set when 'wan_mode' is 'cv-pathfinder'.", - ) + if node_defined_region not in self.inputs.cv_pathfinder_regions: + msg = "The 'cv_pathfinder_region' defined at the node level could not be found under the 'cv_pathfinder_regions' key." + raise AristaAvdInvalidInputsError(msg) - return get_item( - regions, - "name", - node_defined_region, - required=True, - custom_error_msg="The 'cv_pathfinder_region' defined at the node level could not be found under the 'cv_pathfinder_regions' key.", - ) + return self.inputs.cv_pathfinder_regions[node_defined_region] @property def wan_zone(self: SharedUtils) -> dict: @@ -322,10 +263,15 @@ def wan_zone(self: SharedUtils) -> dict: Currently, only one default zone with ID 1 is supported. """ # Injecting default zone with id 1. - return {"name": f"{self.wan_region['name']}-ZONE", "id": 1} + if self.wan_region is None: + # Should never happen but just in case. + msg = "Could not find 'cv_pathfinder_region' so it is not possible to auto-generate the zone." + raise AristaAvdInvalidInputsError(msg) + + return {"name": f"{self.wan_region.name}-ZONE", "id": 1} @cached_property - def filtered_wan_route_servers(self: SharedUtils) -> dict: + def filtered_wan_route_servers(self: SharedUtils) -> EosDesigns.WanRouteServers: """ Return a dict keyed by Wan RR based on the the wan_mode type with only the path_groups the router should connect to. @@ -334,18 +280,17 @@ def filtered_wan_route_servers(self: SharedUtils) -> dict: If no peer_fact is found the variables are required in the inventory. """ - wan_route_servers = {} + filtered_wan_route_servers = EosDesigns.WanRouteServers() - wan_route_servers_list = get(self.hostvars, "wan_route_servers", default=[]) - - for wan_rs_dict in natural_sort(wan_route_servers_list, sort_key="hostname"): - # These remote gw can be outside of the inventory - wan_rs = wan_rs_dict["hostname"] - - if wan_rs == self.hostname: + for org_wan_rs in self.inputs.wan_route_servers._natural_sorted(): + if org_wan_rs.hostname == self.hostname: # Don't add yourself continue - if (peer_facts := self.get_peer_facts(wan_rs, required=False)) is not None: + + wan_rs = org_wan_rs._deepcopy() + + # These remote gw can be outside of the inventory + if (peer_facts := self.get_peer_facts(wan_rs.hostname, required=False)) is not None: # Found a matching server in inventory bgp_as = peer_facts.get("bgp_as") @@ -355,48 +300,70 @@ def filtered_wan_route_servers(self: SharedUtils) -> dict: raise AristaAvdError(msg) # Prefer values coming from the input variables over peer facts - vtep_ip = get(wan_rs_dict, "vtep_ip", default=peer_facts.get("vtep_ip")) - wan_path_groups = get(wan_rs_dict, "path_groups", default=peer_facts.get("wan_path_groups")) + if not wan_rs.vtep_ip: + if not (peer_vtep_ip := peer_facts.get("vtep_ip")): + msg = ( + f"'vtep_ip' is missing for peering with {wan_rs}, either set it in under 'wan_route_servers' or something is wrong with the peer" + " facts." + ) + raise AristaAvdInvalidInputsError(msg) + wan_rs.vtep_ip = peer_vtep_ip + + if not wan_rs.path_groups: + if not (peer_path_groups := peer_facts.get("wan_path_groups")): + msg = ( + f"'wan_path_groups' is missing for peering with {wan_rs}, either set it in under 'wan_route_servers'" + " or something is wrong with the peer facts." + ) + raise AristaAvdInvalidInputsError(msg) + + # We cannot coerce or load with _from_list() since the data models are not compatible. + wan_rs.path_groups = EosDesigns.WanRouteServersItem.PathGroups( + [ + EosDesigns.WanRouteServersItem.PathGroupsItem( + name=peer_path_group["name"], + interfaces=EosDesigns.WanRouteServersItem.PathGroupsItem.Interfaces( + [ + EosDesigns.WanRouteServersItem.PathGroupsItem.InterfacesItem( + name=interface["name"], public_ip=interface.get("public_ip") + ) + for interface in peer_path_group.get("_interfaces", []) + ] + ), + ) + for peer_path_group in peer_path_groups + ] + ) - if vtep_ip is None: + else: + # Retrieve the values from the dictionary, making them required if the peer_facts were not found + if not wan_rs.vtep_ip: msg = ( - f"'vtep_ip' is missing for peering with {wan_rs}, either set it in under 'wan_route_servers' or something is wrong with the peer" - " facts." + f"'vtep_ip' is missing for peering with {wan_rs} which was not found in the inventory. Either set it in under 'wan_route_servers'" + " or check your inventory." ) raise AristaAvdInvalidInputsError(msg) - if wan_path_groups is None: + + if not wan_rs.path_groups: msg = ( - f"'wan_path_groups' is missing for peering with {wan_rs}, either set it in under 'wan_route_servers'" - " or something is wrong with the peer facts." + f"'path_groups' is missing for peering with {wan_rs} which was not found in the inventory, Either set it in under 'wan_route_servers'" + " or check your inventory." ) raise AristaAvdInvalidInputsError(msg) - else: - # Retrieve the values from the dictionary, making them required if the peer_facts were not found - vtep_ip = get(wan_rs_dict, "vtep_ip", required=True) - wan_path_groups = get( - wan_rs_dict, - "path_groups", - required=True, - custom_error_msg=( - f"'path_groups' is missing for peering with {wan_rs} which was not found in the inventory, either set it in under 'wan_route_servers'" - " or check your inventory." - ), - ) # Filtering wan_path_groups to only take the ones this device uses to connect to pathfinders. - wan_rs_result_dict = { - "vtep_ip": vtep_ip, - "wan_path_groups": [path_group for path_group in wan_path_groups if self.should_connect_to_wan_rs([path_group["name"]])], - } + wan_rs.path_groups = EosDesigns.WanRouteServersItem.PathGroups( + [path_group for path_group in wan_rs.path_groups if self.should_connect_to_wan_rs([path_group.name])] + ) # If no common path-group then skip # TODO: - this may need to change when `import` path-groups is available - if len(wan_rs_result_dict["wan_path_groups"]) > 0: - wan_route_servers[wan_rs] = strip_empties_from_dict(wan_rs_result_dict) + if wan_rs.path_groups: + filtered_wan_route_servers.append(wan_rs) - return wan_route_servers + return filtered_wan_route_servers - def should_connect_to_wan_rs(self: SharedUtils, path_groups: list) -> bool: + def should_connect_to_wan_rs(self: SharedUtils, path_group_names: list[str]) -> bool: """ This helper implements whether or not a connection to the wan_router_server should be made or not based on a list of path-groups. @@ -405,14 +372,14 @@ def should_connect_to_wan_rs(self: SharedUtils, path_groups: list) -> bool: `connected_to_pathfinder` is not False. """ return any( - local_path_group["name"] in path_groups and any(wan_interface["connected_to_pathfinder"] for wan_interface in local_path_group["interfaces"]) + local_path_group.name in path_group_names and any(wan_interface["connected_to_pathfinder"] for wan_interface in local_path_group._interfaces) for local_path_group in self.wan_local_path_groups ) @cached_property def is_cv_pathfinder_router(self: SharedUtils) -> bool: """Return True is the current wan_mode is cv-pathfinder and the device is a wan router.""" - return self.wan_mode == "cv-pathfinder" and self.is_wan_router + return self.inputs.wan_mode == "cv-pathfinder" and self.is_wan_router @cached_property def is_cv_pathfinder_client(self: SharedUtils) -> bool: @@ -442,33 +409,22 @@ 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.switch_data_node_group_nodes) == 2): + if not self.is_cv_pathfinder_client or self.node_group_is_primary_and_peer_hostname is None: return False - if (ha_enabled := get(self.switch_data_combined, "wan_ha.enabled")) is None: + if self.node_config.wan_ha.enabled is None: msg = ( "Placing two WAN routers in a common node group will trigger WAN HA in a future AVD release. " "Currently WAN HA is in preview, so it will not be automatically enabled. " "To avoid unplanned configuration changes once the feature is released, " "it is currently required to set 'wan_ha.enabled' to 'true' or 'false'." ) - raise AristaAvdError( - msg, - ) - return ha_enabled + raise AristaAvdError(msg) + return self.node_config.wan_ha.enabled @cached_property def wan_ha_ipsec(self: SharedUtils) -> bool: - return self.wan_ha and get(self.switch_data_combined, "wan_ha.ipsec", default=True) - - @cached_property - def wan_ha_path_group_name(self: SharedUtils) -> str: - """ - Return HA path group name for the WAN design. - - Used in both network services and overlay python modules. - """ - return get(self.hostvars, "wan_ha.lan_ha_path_group_name", default="LAN_HA") + return self.wan_ha and self.node_config.wan_ha.ipsec @cached_property def is_first_ha_peer(self: SharedUtils) -> bool: @@ -477,29 +433,19 @@ def is_first_ha_peer(self: SharedUtils) -> bool: This should be called only from functions which have checked that HA is enabled. """ - return self.switch_data_node_group_nodes[0]["name"] == 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: """Return the name of the WAN HA peer.""" if not self.wan_ha: return None - if self.is_first_ha_peer: - return self.switch_data_node_group_nodes[1]["name"] - if self.switch_data_node_group_nodes[1]["name"] == self.hostname: - return self.switch_data_node_group_nodes[0]["name"] - msg = "Unable to find WAN HA peer within same node group" - raise AristaAvdError(msg) - @cached_property - def configured_wan_ha_mtu(self: SharedUtils) -> int: - """Read the device wan_ha.mtu node settings.""" - return get(self.switch_data_combined, "wan_ha.mtu", default=9194) + if self.node_group_is_primary_and_peer_hostname is not None: + return self.node_group_is_primary_and_peer_hostname[1] - @cached_property - def configured_wan_ha_interfaces(self: SharedUtils) -> set: - """Read the device wan_ha.ha_interfaces node settings.""" - return get(self.switch_data_combined, "wan_ha.ha_interfaces", default=[]) + msg = "Unable to find WAN HA peer within same node group" + raise AristaAvdError(msg) @cached_property def vrf_default_uplinks(self: SharedUtils) -> list: @@ -522,7 +468,7 @@ def use_uplinks_for_wan_ha(self: SharedUtils) -> bool: Raises: AristaAvdError: when the list of configured interfaces is a mix of uplinks and none uplinks. """ - interfaces = set(self.configured_wan_ha_interfaces) + interfaces = set(self.node_config.wan_ha.ha_interfaces) uplink_interfaces = set(self.vrf_default_uplink_interfaces) if interfaces.issubset(uplink_interfaces): @@ -537,13 +483,13 @@ def wan_ha_interfaces(self: SharedUtils) -> list: """ Return the list of interfaces for WAN HA. - If using uplinks for WAN HA, returns the filtered uplinks if self.configured_wan_ha_interfaces is not empty + If using uplinks for WAN HA, returns the filtered uplinks if self.node_config.wan_ha.ha_interfaces is not empty else returns all of them. """ if self.use_uplinks_for_wan_ha: - return natural_sort(set(self.configured_wan_ha_interfaces)) or self.vrf_default_uplink_interfaces + return natural_sort(set(self.node_config.wan_ha.ha_interfaces)) or self.vrf_default_uplink_interfaces # Using node values - return natural_sort(set(self.configured_wan_ha_interfaces), "name") + return natural_sort(set(self.node_config.wan_ha.ha_interfaces)) @cached_property def wan_ha_port_channel_id(self: SharedUtils) -> int: @@ -552,7 +498,7 @@ def wan_ha_port_channel_id(self: SharedUtils) -> int: If not provided, computed from the list of configured members. """ - return get(self.switch_data_combined, "wan_ha.port_channel_id", default=int("".join(findall(r"\d", self.wan_ha_interfaces[0])))) + return default(self.node_config.wan_ha.port_channel_id, int("".join(findall(r"\d", self.wan_ha_interfaces[0])))) @cached_property def use_port_channel_for_direct_ha(self: SharedUtils) -> bool: @@ -567,9 +513,9 @@ def use_port_channel_for_direct_ha(self: SharedUtils) -> bool: if self.use_uplinks_for_wan_ha: return False - interfaces = set(self.configured_wan_ha_interfaces) + interfaces = set(self.node_config.wan_ha.ha_interfaces) - return len(interfaces) > 1 or get(self.switch_data_combined, "wan_ha.use_port_channel_for_direct_ha", True) + return len(interfaces) > 1 or self.node_config.wan_ha.use_port_channel_for_direct_ha @cached_property def wan_ha_peer_ip_addresses(self: SharedUtils) -> list: @@ -582,7 +528,7 @@ def wan_ha_peer_ip_addresses(self: SharedUtils) -> list: if self.use_uplinks_for_wan_ha: peer_facts = self.get_peer_facts(self.wan_ha_peer, required=True) vrf_default_peer_uplinks = [uplink for uplink in get(peer_facts, "uplinks", required=True) if get(uplink, "vrf") is None] - interfaces = set(self.configured_wan_ha_interfaces) + interfaces = set(self.node_config.wan_ha.ha_interfaces) for uplink in vrf_default_peer_uplinks: if not interfaces or uplink["interface"] in interfaces: ip_address = get( @@ -590,7 +536,7 @@ def wan_ha_peer_ip_addresses(self: SharedUtils) -> list: "ip_address", required=True, custom_error_msg=( - f"The uplink interface {uplink['interface']} used as WAN LAN HA on the remote peer {self.wan_ha_peer} does not have an IP address.", + f"The uplink interface {uplink['interface']} used as WAN LAN HA on the remote peer {self.wan_ha_peer} does not have an IP address." ), ) prefix_length = uplink["prefix_length"] @@ -610,7 +556,7 @@ def wan_ha_ip_addresses(self: SharedUtils) -> list: ip_addresses = [] if self.use_uplinks_for_wan_ha: - interfaces = set(self.configured_wan_ha_interfaces) + interfaces = set(self.node_config.wan_ha.ha_interfaces) for uplink in self.vrf_default_uplinks: if not interfaces or uplink["interface"] in interfaces: ip_address = get( @@ -630,12 +576,10 @@ def wan_ha_ip_addresses(self: SharedUtils) -> list: @cached_property def wan_ha_ipv4_pool(self: SharedUtils) -> str: """Return the configured wan_ha.ha_ipv4_pool.""" - return get( - self.switch_data_combined, - "wan_ha.ha_ipv4_pool", - required=True, - custom_error_msg="Missing `wan_ha.ha_ipv4_pool` node settings to allocate an IP address to defined HA interface.", - ) + if not self.node_config.wan_ha.ha_ipv4_pool: + msg = "Missing `wan_ha.ha_ipv4_pool` node settings to allocate an IP address to defined HA interface." + raise AristaAvdInvalidInputsError(msg) + return self.node_config.wan_ha.ha_ipv4_pool def generate_lb_policy_name(self: SharedUtils, name: str) -> str: """Returns LB-{name}.""" @@ -644,11 +588,7 @@ def generate_lb_policy_name(self: SharedUtils, name: str) -> str: @cached_property def wan_stun_dtls_profile_name(self: SharedUtils) -> str | None: """Return the DTLS profile name to use for STUN for WAN.""" - if not self.is_wan_router or get(self.hostvars, "wan_stun_dtls_disable") is True: + if not self.is_wan_router or self.inputs.wan_stun_dtls_disable: return None - return get(self.hostvars, "wan_stun_dtls_profile_name", default="STUN-DTLS") - - @cached_property - def wan_encapsulation(self: SharedUtils) -> str: - return get(self.hostvars, "wan_encapsulation", default="path-selection") + return self.inputs.wan_stun_dtls_profile_name diff --git a/python-avd/pyavd/_eos_designs/structured_config/__init__.py b/python-avd/pyavd/_eos_designs/structured_config/__init__.py index c29309a4359..a305d68c84b 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/__init__.py +++ b/python-avd/pyavd/_eos_designs/structured_config/__init__.py @@ -6,6 +6,7 @@ from collections import ChainMap from typing import TYPE_CHECKING +from pyavd._eos_designs.schema import EosDesigns from pyavd._eos_designs.shared_utils import SharedUtils from pyavd._utils import get, merge @@ -88,11 +89,14 @@ def get_structured_config( structured_config = {} module_vars = ChainMap(structured_config, vars) + # Load input vars into the EosDesigns data class. + inputs = EosDesigns._from_dict(vars) + # Initialize SharedUtils class to be passed to each python_module below. - shared_utils = SharedUtils(hostvars=module_vars, templar=templar, schema=input_schema_tools.avdschema) + shared_utils = SharedUtils(hostvars=module_vars, inputs=inputs, templar=templar, schema=input_schema_tools.avdschema) for cls in AVD_STRUCTURED_CONFIG_CLASSES: - eos_designs_module: AvdFacts = cls(module_vars, shared_utils) + eos_designs_module: AvdFacts = cls(hostvars=module_vars, inputs=inputs, shared_utils=shared_utils) results = eos_designs_module.render() # Modules can return a dict or a list of dicts 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 e55a255ffb7..315abd2340d 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/base/__init__.py +++ b/python-avd/pyavd/_eos_designs/structured_config/base/__init__.py @@ -4,16 +4,20 @@ from __future__ import annotations from functools import cached_property +from typing import TYPE_CHECKING from pyavd._eos_designs.avdfacts import AvdFacts -from pyavd._errors import AristaAvdInvalidInputsError -from pyavd._utils import get, get_item, strip_empties_from_dict, strip_null_from_data +from pyavd._errors import AristaAvdInvalidInputsError, AristaAvdMissingVariableError +from pyavd._utils import default, get, strip_empties_from_dict, strip_null_from_data from pyavd.j2filters import natural_sort from .ntp import NtpMixin from .router_general import RouterGeneralMixin from .snmp_server import SnmpServerMixin +if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + class AvdStructuredConfigBase(AvdFacts, NtpMixin, SnmpServerMixin, RouterGeneralMixin): """ @@ -35,7 +39,7 @@ def hostname(self) -> str: @cached_property def is_deployed(self) -> bool: - return self.shared_utils.is_deployed + return self.inputs.is_deployed @cached_property def serial_number(self) -> str | None: @@ -52,10 +56,8 @@ def router_bgp(self) -> dict | None: if self.shared_utils.bgp_as is None: return None - platform_bgp_update_wait_for_convergence = ( - get(self.shared_utils.platform_settings, "feature_support.bgp_update_wait_for_convergence", default=True) is True - ) - platform_bgp_update_wait_install = get(self.shared_utils.platform_settings, "feature_support.bgp_update_wait_install", default=True) is True + platform_bgp_update_wait_for_convergence = self.shared_utils.platform_settings.feature_support.bgp_update_wait_for_convergence + platform_bgp_update_wait_install = self.shared_utils.platform_settings.feature_support.bgp_update_wait_install if self.shared_utils.is_wan_router: # Special defaults for WAN routers @@ -67,33 +69,33 @@ def router_bgp(self) -> dict | None: router_bgp = { "as": self.shared_utils.bgp_as, - "router_id": self.shared_utils.router_id if not self.shared_utils.use_router_general_for_router_id else None, - "distance": get(self._hostvars, "bgp_distance"), - "bgp_defaults": get(self.shared_utils.switch_data_combined, "bgp_defaults"), + "router_id": self.shared_utils.router_id if not self.inputs.use_router_general_for_router_id else None, + "distance": self.inputs.bgp_distance._as_dict() or None, + "bgp_defaults": self.shared_utils.node_config.bgp_defaults._as_list() or None, "bgp": { "default": { - "ipv4_unicast": get(self._hostvars, "bgp_default_ipv4_unicast", default=False), + "ipv4_unicast": self.inputs.bgp_default_ipv4_unicast, }, }, "maximum_paths": { - "paths": get(self._hostvars, "bgp_maximum_paths", default=default_maximum_paths), - "ecmp": get(self._hostvars, "bgp_ecmp", default=default_ecmp), + "paths": self.inputs.bgp_maximum_paths or default_maximum_paths, + "ecmp": self.inputs.bgp_ecmp or default_ecmp, }, "redistribute": self._router_bgp_redistribute_routes, } - if get(self._hostvars, "bgp_update_wait_for_convergence", default=False) is True and platform_bgp_update_wait_for_convergence: + if self.inputs.bgp_update_wait_for_convergence and platform_bgp_update_wait_for_convergence: router_bgp.setdefault("updates", {})["wait_for_convergence"] = True - if get(self._hostvars, "bgp_update_wait_install", default=True) is True and platform_bgp_update_wait_install: + if self.inputs.bgp_update_wait_install and platform_bgp_update_wait_install: router_bgp.setdefault("updates", {})["wait_install"] = True - if get(self._hostvars, "bgp_graceful_restart.enabled") is True: + if self.inputs.bgp_graceful_restart.enabled: router_bgp.update( { "graceful_restart": { "enabled": True, - "restart_time": get(self._hostvars, "bgp_graceful_restart.restart_time", default=300), + "restart_time": self.inputs.bgp_graceful_restart.restart_time, }, }, ) @@ -127,19 +129,19 @@ def static_routes(self) -> list | None: if self.shared_utils.mgmt_gateway is None: return None - if (mgmt_destination_networks := get(self._hostvars, "mgmt_destination_networks")) is not None: + if self.inputs.mgmt_destination_networks: return [ { - "vrf": self.shared_utils.mgmt_interface_vrf, + "vrf": self.inputs.mgmt_interface_vrf, "destination_address_prefix": mgmt_destination_network, "gateway": self.shared_utils.mgmt_gateway, } - for mgmt_destination_network in mgmt_destination_networks + for mgmt_destination_network in self.inputs.mgmt_destination_networks ] return [ { - "vrf": self.shared_utils.mgmt_interface_vrf, + "vrf": self.inputs.mgmt_interface_vrf, "destination_address_prefix": "0.0.0.0/0", "gateway": self.shared_utils.mgmt_gateway, } @@ -148,22 +150,22 @@ def static_routes(self) -> list | None: @cached_property def ipv6_static_routes(self) -> list | None: """ipv6_static_routes set based on ipv6_mgmt_gateway, ipv6_mgmt_destination_networks and mgmt_interface_vrf.""" - if self.shared_utils.ipv6_mgmt_gateway is None or self.shared_utils.ipv6_mgmt_ip is None: + if self.shared_utils.ipv6_mgmt_gateway is None or self.shared_utils.node_config.ipv6_mgmt_ip is None: return None - if (ipv6_mgmt_destination_networks := get(self._hostvars, "ipv6_mgmt_destination_networks")) is not None: + if self.inputs.ipv6_mgmt_destination_networks: return [ { - "vrf": self.shared_utils.mgmt_interface_vrf, + "vrf": self.inputs.mgmt_interface_vrf, "destination_address_prefix": mgmt_destination_network, "gateway": self.shared_utils.ipv6_mgmt_gateway, } - for mgmt_destination_network in ipv6_mgmt_destination_networks + for mgmt_destination_network in self.inputs.ipv6_mgmt_destination_networks ] return [ { - "vrf": self.shared_utils.mgmt_interface_vrf, + "vrf": self.inputs.mgmt_interface_vrf, "destination_address_prefix": "::/0", "gateway": self.shared_utils.ipv6_mgmt_gateway, }, @@ -181,7 +183,7 @@ def ip_routing(self) -> bool | None: For other devices only configure if "always_configure_ip_routing" is True. """ - if not self.shared_utils.underlay_router and not self.shared_utils.always_configure_ip_routing: + if not self.shared_utils.underlay_router and not self.shared_utils.node_config.always_configure_ip_routing: return None if self.ip_routing_ipv6_interfaces is True: @@ -191,20 +193,20 @@ def ip_routing(self) -> bool | None: @cached_property def ipv6_unicast_routing(self) -> bool | None: """ipv6_unicast_routing set based on underlay_rfc5549 and underlay_ipv6.""" - if not self.shared_utils.underlay_router and not self.shared_utils.always_configure_ip_routing: + if not self.shared_utils.underlay_router and not self.shared_utils.node_config.always_configure_ip_routing: return None - if self.shared_utils.underlay_rfc5549 or self.shared_utils.underlay_ipv6: + if self.inputs.underlay_rfc5549 or self.shared_utils.underlay_ipv6: return True return None @cached_property def ip_routing_ipv6_interfaces(self) -> bool | None: """ip_routing_ipv6_interfaces set based on underlay_rfc5549 variable.""" - if not self.shared_utils.underlay_router and not self.shared_utils.always_configure_ip_routing: + if not self.shared_utils.underlay_router and not self.shared_utils.node_config.always_configure_ip_routing: return None - if self.shared_utils.underlay_rfc5549: + if self.inputs.underlay_rfc5549: return True return None @@ -223,7 +225,7 @@ def router_multicast(self) -> dict | None: @cached_property def hardware_counters(self) -> dict | None: """hardware_counters set based on hardware_counters.features variable.""" - return get(self._hostvars, "hardware_counters") + return self.inputs.hardware_counters._as_dict() or None @cached_property def hardware(self) -> dict | None: @@ -232,18 +234,18 @@ def hardware(self) -> dict | None: Converting nested dict to list of dict to support avd_v4.0. """ - platform_speed_groups = get(self._hostvars, "platform_speed_groups") + platform_speed_groups = self.inputs.platform_speed_groups switch_platform = self.shared_utils.platform - if platform_speed_groups is None or switch_platform is None: + if not platform_speed_groups or switch_platform is None: + return None + + if switch_platform not in platform_speed_groups: return None tmp_speed_groups = {} - for platform_item in platform_speed_groups: - if platform_item["platform"] == switch_platform: - speeds = platform_item.get("speeds") - for speed in natural_sort(speeds, "speed"): - for speed_group in speed["speed_groups"]: - tmp_speed_groups[speed_group] = speed["speed"] + for speed in platform_speed_groups[switch_platform].speeds._natural_sorted(): + for speed_group in speed.speed_groups: + tmp_speed_groups[speed_group] = speed.speed if tmp_speed_groups: hardware = {"speed_groups": []} @@ -264,7 +266,7 @@ def daemon_terminattr(self) -> dict | None: else: """ - cvp_instance_ip_list = get(self._hostvars, "cvp_instance_ips", []) + cvp_instance_ip_list = self.inputs.cvp_instance_ips if not cvp_instance_ip_list: return None @@ -276,13 +278,13 @@ def daemon_terminattr(self) -> dict | None: daemon_terminattr["cvauth"] = { "method": "token-secure", # Ignoring sonar-lint false positive for tmp path since this is config for EOS - "token_file": get(self._hostvars, "cvp_token_file", "/tmp/cv-onboarding-token"), # NOSONAR # noqa: S108 + "token_file": self.inputs.cvp_token_file or "/tmp/cv-onboarding-token", # NOSONAR # noqa: S108 } else: # updating for cvp_on_prem_ips - cv_address = f"{cvp_instance_ip}:{get(self._hostvars, 'terminattr_ingestgrpcurl_port', default=9910)}" + cv_address = f"{cvp_instance_ip}:{self.inputs.terminattr_ingestgrpcurl_port}" daemon_terminattr["cvaddrs"].append(cv_address) - if (cvp_ingestauth_key := get(self._hostvars, "cvp_ingestauth_key")) is not None: + if (cvp_ingestauth_key := self.inputs.cvp_ingestauth_key) is not None: daemon_terminattr["cvauth"] = { "method": "key", "key": cvp_ingestauth_key, @@ -291,13 +293,13 @@ def daemon_terminattr(self) -> dict | None: daemon_terminattr["cvauth"] = { "method": "token", # Ignoring sonar-lint false positive for tmp path since this is config for EOS - "token_file": get(self._hostvars, "cvp_token_file", "/tmp/token"), # NOSONAR # noqa: S108 + "token_file": self.inputs.cvp_token_file or "/tmp/token", # NOSONAR # noqa: S108 } - daemon_terminattr["cvvrf"] = self.shared_utils.mgmt_interface_vrf - daemon_terminattr["smashexcludes"] = get(self._hostvars, "terminattr_smashexcludes", default="ale,flexCounter,hardware,kni,pulse,strata") - daemon_terminattr["ingestexclude"] = get(self._hostvars, "terminattr_ingestexclude", default="/Sysdb/cell/1/agent,/Sysdb/cell/2/agent") - daemon_terminattr["disable_aaa"] = get(self._hostvars, "terminattr_disable_aaa", False) + daemon_terminattr["cvvrf"] = self.inputs.mgmt_interface_vrf + daemon_terminattr["smashexcludes"] = self.inputs.terminattr_smashexcludes + daemon_terminattr["ingestexclude"] = self.inputs.terminattr_ingestexclude + daemon_terminattr["disable_aaa"] = self.inputs.terminattr_disable_aaa return daemon_terminattr @@ -307,14 +309,7 @@ def vlan_internal_order(self) -> dict | None: if self.shared_utils.wan_role: return None - default_internal_vlan_order = { - "allocation": "ascending", - "range": { - "beginning": 1006, - "ending": 1199, - }, - } - return get(self._hostvars, "internal_vlan_order", default=default_internal_vlan_order) + return self.inputs.internal_vlan_order._as_dict() @cached_property def aaa_root(self) -> dict: @@ -342,7 +337,7 @@ def transceiver_qsfp_default_mode_4x10(self) -> bool: @cached_property def event_monitor(self) -> dict | None: - """event_monitor set based on event_monitor data-model.""" + """event_monitor set based on event_monitor data-model. TODO: add to schema.""" if get(self._hostvars, "event_monitor") is True: return {"enabled": "true"} return None @@ -350,11 +345,11 @@ def event_monitor(self) -> dict | None: @cached_property def event_handlers(self) -> list | None: """event_handlers set based on event_handlers data-model.""" - return get(self._hostvars, "event_handlers") + return self.inputs.event_handlers._as_list() or None @cached_property def load_interval(self) -> dict | None: - """load_interval set based on load_interval_default variable.""" + """load_interval set based on load_interval_default variable. TODO: add to schema.""" if (load_interval_default := get(self._hostvars, "load_interval_default")) is not None: return {"default": load_interval_default} return None @@ -362,11 +357,12 @@ def load_interval(self) -> dict | None: @cached_property def queue_monitor_length(self) -> dict | None: """queue_monitor_length set based on queue_monitor_length data-model and platform_settings.feature_support.queue_monitor_length_notify fact.""" - if (queue_monitor_length := get(self._hostvars, "queue_monitor_length")) is None: + if not self.inputs.queue_monitor_length: return None # Remove notifying key if not supported by the platform settings. - if not self.shared_utils.platform_settings_feature_support_queue_monitor_length_notify: + queue_monitor_length = self.inputs.queue_monitor_length._as_dict() + if not self.shared_utils.platform_settings.feature_support.queue_monitor_length_notify: queue_monitor_length.pop("notifying", None) return queue_monitor_length @@ -377,20 +373,18 @@ def ip_name_servers(self) -> list | None: ip_name_servers = [ { "ip_address": name_server, - "vrf": self.shared_utils.mgmt_interface_vrf, + "vrf": self.inputs.mgmt_interface_vrf, } - for name_server in get(self._hostvars, "name_servers", default=[]) + for name_server in self.inputs.name_servers ] - if ip_name_servers: - return ip_name_servers - return None + return ip_name_servers or None @cached_property def redundancy(self) -> dict | None: """Redundancy set based on redundancy data-model.""" - if get(self._hostvars, "redundancy") is not None: - return {"protocol": get(self._hostvars, "redundancy.protocol")} + if self.inputs.redundancy.protocol: + return {"protocol": self.inputs.redundancy.protocol} return None @cached_property @@ -408,8 +402,8 @@ def spanning_tree(self) -> dict | None: if not self.shared_utils.network_services_l2: return {"mode": "none"} - spanning_tree_root_super = get(self.shared_utils.switch_data_combined, "spanning_tree_root_super") - spanning_tree_mode = get(self.shared_utils.switch_data_combined, "spanning_tree_mode") + spanning_tree_root_super = self.shared_utils.node_config.spanning_tree_root_super + spanning_tree_mode = self.shared_utils.node_config.spanning_tree_mode if spanning_tree_root_super is not True and spanning_tree_mode is None: return None @@ -419,7 +413,7 @@ def spanning_tree(self) -> dict | None: if spanning_tree_mode is not None: spanning_tree["mode"] = spanning_tree_mode - priority = get(self.shared_utils.switch_data_combined, "spanning_tree_priority", default=32768) + priority = self.shared_utils.node_config.spanning_tree_priority # "rapid-pvst" is not included below. Per vlan spanning-tree priorities are set under network-services. if spanning_tree_mode == "mstp": spanning_tree["mst_instances"] = [{"id": "0", "priority": priority}] @@ -430,7 +424,7 @@ def spanning_tree(self) -> dict | None: @cached_property def service_unsupported_transceiver(self) -> dict | None: - """service_unsupported_transceiver based on unsupported_transceiver data-model.""" + """service_unsupported_transceiver based on unsupported_transceiver data-model. TODO: Add to schema - maybe as hidden.""" if (unsupported_transceiver := get(self._hostvars, "unsupported_transceiver")) is not None: return {"license_name": unsupported_transceiver.get("license_name"), "license_key": unsupported_transceiver.get("license_key")} @@ -439,76 +433,70 @@ def service_unsupported_transceiver(self) -> dict | None: @cached_property def local_users(self) -> list | None: """local_users set based on local_users data model.""" - if (local_users := get(self._hostvars, "local_users")) is None: + if not self.inputs.local_users: return None - return natural_sort(local_users, "name") + return [user._as_dict() for user in self.inputs.local_users._natural_sorted()] @cached_property def clock(self) -> dict | None: """Clock set based on timezone variable.""" - if (timezone := get(self._hostvars, "timezone")) is not None: - return {"timezone": timezone} + if self.inputs.timezone: + return {"timezone": self.inputs.timezone} return None @cached_property def vrfs(self) -> list: """Vrfs set based on mgmt_interface_vrf variable.""" - mgmt_vrf_routing = get(self._hostvars, "mgmt_vrf_routing", default=False) vrf_settings = { - "name": self.shared_utils.mgmt_interface_vrf, - "ip_routing": mgmt_vrf_routing, + "name": self.inputs.mgmt_interface_vrf, + "ip_routing": self.inputs.mgmt_vrf_routing, } - if self.shared_utils.ipv6_mgmt_ip is not None: - vrf_settings["ipv6_routing"] = mgmt_vrf_routing + if self.shared_utils.node_config.ipv6_mgmt_ip is not None: + vrf_settings["ipv6_routing"] = self.inputs.mgmt_vrf_routing return [vrf_settings] @cached_property def management_interfaces(self) -> list | None: """management_interfaces set based on mgmt_interface, mgmt_ip, ipv6_mgmt_ip facts, mgmt_gateway, ipv6_mgmt_gateway and mgmt_interface_vrf variables.""" - mgmt_interface = self.shared_utils.mgmt_interface - if ( - mgmt_interface is not None - and self.shared_utils.mgmt_interface_vrf is not None - and (self.shared_utils.mgmt_ip is not None or self.shared_utils.ipv6_mgmt_ip is not None) - ): + if self.shared_utils.node_config.mgmt_ip or self.shared_utils.node_config.ipv6_mgmt_ip: interface_settings = { - "name": mgmt_interface, - "description": get(self._hostvars, "mgmt_interface_description", default="OOB_MANAGEMENT"), + "name": self.shared_utils.mgmt_interface, + "description": self.inputs.mgmt_interface_description, "shutdown": False, - "vrf": self.shared_utils.mgmt_interface_vrf, - "ip_address": self.shared_utils.mgmt_ip, + "vrf": self.inputs.mgmt_interface_vrf, + "ip_address": self.shared_utils.node_config.mgmt_ip, "gateway": self.shared_utils.mgmt_gateway, "type": "oob", } """ inserting ipv6 variables if ipv6_mgmt_ip is set """ - if self.shared_utils.ipv6_mgmt_ip is not None: + if self.shared_utils.node_config.ipv6_mgmt_ip: interface_settings.update( { "ipv6_enable": True, - "ipv6_address": self.shared_utils.ipv6_mgmt_ip, + "ipv6_address": self.shared_utils.node_config.ipv6_mgmt_ip, "ipv6_gateway": self.shared_utils.ipv6_mgmt_gateway, }, ) - return [interface_settings] + return [strip_empties_from_dict(interface_settings)] return None @cached_property def management_security(self) -> dict | None: """Return structured config for management_security.""" - if (entropy_sources := get(self.shared_utils.platform_settings, "security_entropy_sources")) is not None: - return {"entropy_sources": entropy_sources} + if entropy_sources := self.shared_utils.platform_settings.security_entropy_sources: + return {"entropy_sources": entropy_sources._as_dict(include_default_values=True)} return None @cached_property def tcam_profile(self) -> dict | None: """tcam_profile set based on platform_settings.tcam_profile fact.""" - if (tcam_profile := get(self.shared_utils.platform_settings, "tcam_profile")) is not None: + if tcam_profile := self.shared_utils.platform_settings.tcam_profile: return {"system": tcam_profile} return None @@ -522,14 +510,14 @@ def platform(self) -> dict | None: * data_plane_cpu_allocation_max. """ platform = {} - if (lag_hardware_only := get(self.shared_utils.platform_settings, "lag_hardware_only")) is not None: + if (lag_hardware_only := self.shared_utils.platform_settings.lag_hardware_only) is not None: platform["sand"] = {"lag": {"hardware_only": lag_hardware_only}} - trident_forwarding_table_partition = get(self.shared_utils.platform_settings, "trident_forwarding_table_partition") - if trident_forwarding_table_partition is not None and self.shared_utils.evpn_multicast: + trident_forwarding_table_partition = self.shared_utils.platform_settings.trident_forwarding_table_partition + if trident_forwarding_table_partition and self.shared_utils.evpn_multicast: platform["trident"] = {"forwarding_table_partition": trident_forwarding_table_partition} - if (cpu_max_allocation := get(self.shared_utils.switch_data_combined, "data_plane_cpu_allocation_max")) is not None: + if (cpu_max_allocation := self.shared_utils.node_config.data_plane_cpu_allocation_max) is not None: platform["sfe"] = {"data_plane_cpu_allocation_max": cpu_max_allocation} elif self.shared_utils.is_wan_server: # For AutoVPN Route Reflectors and Pathfinders, running on CloudEOS, setting @@ -544,13 +532,13 @@ def platform(self) -> dict | None: @cached_property def mac_address_table(self) -> dict | None: """mac_address_table set based on mac_address_table data-model.""" - if (aging_time := get(self._hostvars, "mac_address_table.aging_time")) is not None: - return {"aging_time": aging_time} + if self.inputs.mac_address_table.aging_time is not None: + return {"aging_time": self.inputs.mac_address_table.aging_time} return None @cached_property def queue_monitor_streaming(self) -> dict | None: - """queue_monitor_streaming set based on queue_monitor_streaming data-model.""" + """queue_monitor_streaming set based on queue_monitor_streaming data-model. TODO: Add to schema.""" enable = get(self._hostvars, "queue_monitor_streaming.enable") vrf = get(self._hostvars, "queue_monitor_streaming.vrf") if enable is not True or vrf is None: @@ -561,27 +549,21 @@ def queue_monitor_streaming(self) -> dict | None: if enable is True: queue_monitor["enable"] = enable - if vrf is not None: - queue_monitor["vrf"] = vrf + queue_monitor["vrf"] = vrf return queue_monitor @cached_property - def management_api_http(self) -> dict | None: + def management_api_http(self) -> dict: """management_api_http set based on management_eapi data-model.""" - if (management_eapi := get(self._hostvars, "management_eapi", default={"enable_https": True})) is None: - return None - - management_api_http = {"enable_vrfs": [{"name": self.shared_utils.mgmt_interface_vrf}]} - management_api = management_eapi.fromkeys(["enable_http", "enable_https", "default_services"]) - for key in dict(management_api): - if (value := management_eapi.get(key)) is not None: - management_api[key] = value - else: - del management_api[key] - - management_api_http.update(management_api) - return management_api_http + return strip_empties_from_dict( + { + "enable_vrfs": [{"name": self.inputs.mgmt_interface_vrf}], + "enable_http": self.inputs.management_eapi.enable_http or None, + "enable_https": self.inputs.management_eapi.enable_https or None, + "default_services": self.inputs.management_eapi.default_services, + } + ) @cached_property def link_tracking_groups(self) -> list | None: @@ -591,20 +573,18 @@ def link_tracking_groups(self) -> list | None: @cached_property def lacp(self) -> dict | None: """Lacp set based on lacp_port_id_range.""" - lacp_port_id_range = get(self.shared_utils.switch_data_combined, "lacp_port_id_range", default={}) - if lacp_port_id_range.get("enabled") is not True: + lacp_port_id_range = self.shared_utils.node_config.lacp_port_id_range + if not lacp_port_id_range.enabled: return None if (switch_id := self.shared_utils.id) is 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.switch_data_node_group_nodes), 1) - port_range = int(get(lacp_port_id_range, "size", default=128)) - port_offset = int(get(lacp_port_id_range, "offset", default=0)) + 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) * port_range) + port_offset - end = (((switch_id - 1) % node_group_length + 1) * port_range) + port_offset + 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 return { "port_id": { @@ -630,85 +610,56 @@ def ptp(self) -> dict | None: """ if not self.shared_utils.ptp_enabled: return None - default_ptp_domain = get(self._hostvars, "ptp_settings.domain", default=127) - default_ptp_priority1 = get(self.shared_utils.node_type_key_data, "default_ptp_priority1", default=127) + default_ptp_domain = self.inputs.ptp_settings.domain + default_ptp_priority1 = self.shared_utils.node_type_key_data.default_ptp_priority1 default_clock_identity = None - priority1 = get(self.shared_utils.switch_data_combined, "ptp.priority1", default=default_ptp_priority1) - priority2 = get(self.shared_utils.switch_data_combined, "ptp.priority2") + priority1 = default(self.shared_utils.node_config.ptp.priority1, default_ptp_priority1) + priority2 = self.shared_utils.node_config.ptp.priority2 if priority2 is None: if self.shared_utils.id is None: msg = f"'id' must be set on '{self.shared_utils.hostname}' to set ptp priority2" raise AristaAvdInvalidInputsError(msg) priority2 = self.shared_utils.id % 256 - default_auto_clock_identity = get(self._hostvars, "ptp_settings.auto_clock_identity", default=True) - if get(self.shared_utils.switch_data_combined, "ptp.auto_clock_identity", default=default_auto_clock_identity) is True: - clock_identity_prefix = get(self.shared_utils.switch_data_combined, "ptp.clock_identity_prefix", default="00:1C:73") + if default(self.shared_utils.node_config.ptp.auto_clock_identity, self.inputs.ptp_settings.auto_clock_identity): + clock_identity_prefix = self.shared_utils.node_config.ptp.clock_identity_prefix default_clock_identity = f"{clock_identity_prefix}:{priority1:02x}:00:{priority2:02x}" ptp = { - "mode": get(self.shared_utils.switch_data_combined, "ptp.mode", default="boundary"), - "mode_one_step": get(self.shared_utils.switch_data_combined, "ptp.mode_one_step"), - "forward_unicast": get(self.shared_utils.switch_data_combined, "ptp.forward_unicast"), - "clock_identity": get(self.shared_utils.switch_data_combined, "ptp.clock_identity", default=default_clock_identity), - "source": {"ip": get(self.shared_utils.switch_data_combined, "ptp.source_ip")}, + "mode": self.shared_utils.node_config.ptp.mode, + "mode_one_step": self.shared_utils.node_config.ptp.mode_one_step or None, # Historic output is without false + "forward_unicast": self.shared_utils.node_config.ptp.forward_unicast or None, # Historic output is without false + "clock_identity": default(self.shared_utils.node_config.ptp.clock_identity, default_clock_identity), + "source": {"ip": self.shared_utils.node_config.ptp.source_ip}, "priority1": priority1, "priority2": priority2, - "ttl": get(self.shared_utils.switch_data_combined, "ptp.ttl"), - "domain": get(self.shared_utils.switch_data_combined, "ptp.domain", default=default_ptp_domain), + "ttl": self.shared_utils.node_config.ptp.ttl, + "domain": default(self.shared_utils.node_config.ptp.domain, default_ptp_domain), "message_type": { "general": { - "dscp": get(self.shared_utils.switch_data_combined, "ptp.dscp.general_messages"), + "dscp": self.shared_utils.node_config.ptp.dscp.general_messages, }, "event": { - "dscp": get(self.shared_utils.switch_data_combined, "ptp.dscp.event_messages"), - }, - }, - "monitor": { - "enabled": get(self.shared_utils.switch_data_combined, "ptp.monitor.enabled", default=True), - "threshold": { - "offset_from_master": get(self.shared_utils.switch_data_combined, "ptp.monitor.threshold.offset_from_master", default=250), - "mean_path_delay": get(self.shared_utils.switch_data_combined, "ptp.monitor.threshold.mean_path_delay", default=1500), - "drop": { - "offset_from_master": get(self.shared_utils.switch_data_combined, "ptp.monitor.threshold.drop.offset_from_master"), - "mean_path_delay": get(self.shared_utils.switch_data_combined, "ptp.monitor.threshold.drop.mean_path_delay"), - }, - }, - "missing_message": { - "intervals": { - "announce": get(self.shared_utils.switch_data_combined, "ptp.monitor.missing_message.intervals.announce"), - "follow_up": get(self.shared_utils.switch_data_combined, "ptp.monitor.missing_message.intervals.follow_up"), - "sync": get(self.shared_utils.switch_data_combined, "ptp.monitor.missing_message.intervals.sync"), - }, - "sequence_ids": { - "enabled": get(self.shared_utils.switch_data_combined, "ptp.monitor.missing_message.sequence_ids.enabled", default=True), - "announce": get(self.shared_utils.switch_data_combined, "ptp.monitor.missing_message.sequence_ids.announce", default=3), - "delay_resp": get(self.shared_utils.switch_data_combined, "ptp.monitor.missing_message.sequence_ids.delay_resp", default=3), - "follow_up": get(self.shared_utils.switch_data_combined, "ptp.monitor.missing_message.sequence_ids.follow_up", default=3), - "sync": get(self.shared_utils.switch_data_combined, "ptp.monitor.missing_message.sequence_ids.sync", default=3), - }, + "dscp": self.shared_utils.node_config.ptp.dscp.event_messages, }, }, + "monitor": self.shared_utils.node_config.ptp.monitor._as_dict(include_default_values=True), } return strip_null_from_data(ptp, (None, {})) @cached_property def eos_cli(self) -> str | None: """Aggregate the values of raw_eos_cli and platform_settings.platform_raw_eos_cli facts.""" - raw_eos_cli = get(self.shared_utils.switch_data_combined, "raw_eos_cli") - platform_raw_eos_cli = get(self.shared_utils.platform_settings, "raw_eos_cli") - if raw_eos_cli is not None or platform_raw_eos_cli is not None: - return "\n".join(filter(None, [raw_eos_cli, platform_raw_eos_cli])) - return None + return "\n".join(filter(None, [self.shared_utils.node_config.raw_eos_cli, self.shared_utils.platform_settings.raw_eos_cli])) or None @cached_property def ip_radius_source_interfaces(self) -> list | None: """Parse source_interfaces.radius and return list of source_interfaces.""" - if (inputs := self._source_interfaces.get("radius")) is None: + if not (inputs := self.inputs.source_interfaces.radius): return None - if source_interfaces := self._build_source_interfaces(inputs.get("mgmt_interface", False), inputs.get("inband_mgmt_interface", False), "IP Radius"): + if source_interfaces := self._build_source_interfaces(inputs.mgmt_interface, inputs.inband_mgmt_interface, "IP Radius"): return source_interfaces return None @@ -716,10 +667,10 @@ def ip_radius_source_interfaces(self) -> list | None: @cached_property def ip_tacacs_source_interfaces(self) -> list | None: """Parse source_interfaces.tacacs and return list of source_interfaces.""" - if (inputs := self._source_interfaces.get("tacacs")) is None: + if not (inputs := self.inputs.source_interfaces.tacacs): return None - if source_interfaces := self._build_source_interfaces(inputs.get("mgmt_interface", False), inputs.get("inband_mgmt_interface", False), "IP Tacacs"): + if source_interfaces := self._build_source_interfaces(inputs.mgmt_interface, inputs.inband_mgmt_interface, "IP Tacacs"): return source_interfaces return None @@ -727,10 +678,10 @@ def ip_tacacs_source_interfaces(self) -> list | None: @cached_property def ip_ssh_client_source_interfaces(self) -> list | None: """Parse source_interfaces.ssh_client and return list of source_interfaces.""" - if (inputs := self._source_interfaces.get("ssh_client")) is None: + if not (inputs := self.inputs.source_interfaces.ssh_client): return None - if source_interfaces := self._build_source_interfaces(inputs.get("mgmt_interface", False), inputs.get("inband_mgmt_interface", False), "IP SSH Client"): + if source_interfaces := self._build_source_interfaces(inputs.mgmt_interface, inputs.inband_mgmt_interface, "IP SSH Client"): return source_interfaces return None @@ -738,14 +689,10 @@ def ip_ssh_client_source_interfaces(self) -> list | None: @cached_property def ip_domain_lookup(self) -> dict | None: """Parse source_interfaces.domain_lookup and return dict with nested source_interfaces list.""" - if (inputs := self._source_interfaces.get("domain_lookup")) is None: + if not (inputs := self.inputs.source_interfaces.domain_lookup): return None - if source_interfaces := self._build_source_interfaces( - inputs.get("mgmt_interface", False), - inputs.get("inband_mgmt_interface", False), - "IP Domain Lookup", - ): + if source_interfaces := self._build_source_interfaces(inputs.mgmt_interface, inputs.inband_mgmt_interface, "IP Domain Lookup"): return {"source_interfaces": source_interfaces} return None @@ -753,14 +700,10 @@ def ip_domain_lookup(self) -> dict | None: @cached_property def ip_http_client_source_interfaces(self) -> list | None: """Parse source_interfaces.http_client and return list of source_interfaces.""" - if (inputs := self._source_interfaces.get("http_client")) is None: + if not (inputs := self.inputs.source_interfaces.http_client): return None - if source_interfaces := self._build_source_interfaces( - inputs.get("mgmt_interface", False), - inputs.get("inband_mgmt_interface", False), - "IP HTTP Client", - ): + if source_interfaces := self._build_source_interfaces(inputs.mgmt_interface, inputs.inband_mgmt_interface, "IP HTTP Client"): return source_interfaces return None @@ -771,19 +714,22 @@ def prefix_lists(self) -> list | None: prefix_lists_in_use = set() for neighbor in self.shared_utils.l3_interfaces_bgp_neighbors: if (prefix_list_in := get(neighbor, "ipv4_prefix_list_in")) and prefix_list_in not in prefix_lists_in_use: - pfx_list = self._get_prefix_list(prefix_list_in) + pfx_list = self._get_prefix_list(prefix_list_in)._as_dict() prefix_lists.append(pfx_list) prefix_lists_in_use.add(prefix_list_in) if (prefix_list_out := get(neighbor, "ipv4_prefix_list_out")) and prefix_list_out not in prefix_lists_in_use: - pfx_list = self._get_prefix_list(prefix_list_out) + pfx_list = self._get_prefix_list(prefix_list_out)._as_dict() prefix_lists.append(pfx_list) prefix_lists_in_use.add(prefix_list_out) return prefix_lists or None - def _get_prefix_list(self, name: str) -> dict: - return get_item(self.shared_utils.ipv4_prefix_list_catalog, "name", name, required=True, var_name=f"ipv4_prefix_list_catalog[name={name}]") + def _get_prefix_list(self, name: str) -> EosDesigns.Ipv4PrefixListCatalogItem: + if name not in self.inputs.ipv4_prefix_list_catalog: + msg = f"ipv4_prefix_list_catalog[name={name}]" + raise AristaAvdMissingVariableError(msg) + return self.inputs.ipv4_prefix_list_catalog[name] @cached_property def route_maps(self) -> list | None: @@ -831,7 +777,7 @@ def route_maps(self) -> list | None: @cached_property def struct_cfgs(self) -> list | None: - if (struct_cfg := get(self.shared_utils.platform_settings, "structured_config")) is not None: - return [struct_cfg] + if self.shared_utils.platform_settings.structured_config: + return [self.shared_utils.platform_settings.structured_config._as_dict(strip_values=())] return None diff --git a/python-avd/pyavd/_eos_designs/structured_config/base/ntp.py b/python-avd/pyavd/_eos_designs/structured_config/base/ntp.py index f181e244ad0..20f22e15afe 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/base/ntp.py +++ b/python-avd/pyavd/_eos_designs/structured_config/base/ntp.py @@ -7,7 +7,7 @@ from typing import TYPE_CHECKING from pyavd._errors import AristaAvdError -from pyavd._utils import get, strip_null_from_data +from pyavd._utils import strip_null_from_data from .utils import UtilsMixin @@ -25,27 +25,26 @@ class NtpMixin(UtilsMixin): @cached_property def ntp(self: AvdStructuredConfigBase) -> dict | None: """Ntp set based on "ntp_settings" data-model.""" - ntp_settings = get(self._hostvars, "ntp_settings") - if not ntp_settings: + if not (ntp_settings := self.inputs.ntp_settings): return None # Since the eos_cli_config_gen data model almost matches, we can copy most data directly. ntp = strip_null_from_data( { - "authenticate": ntp_settings.get("authenticate"), - "authenticate_servers_only": ntp_settings.get("authenticate_servers_only"), - "authentication_keys": ntp_settings.get("authentication_keys"), - "trusted_keys": ntp_settings.get("trusted_keys"), + "authenticate": ntp_settings.authenticate, + "authenticate_servers_only": ntp_settings.authenticate_servers_only, + "authentication_keys": ntp_settings.authentication_keys._as_list() or None, + "trusted_keys": ntp_settings.trusted_keys, }, ) - if "servers" not in ntp_settings: + if not ntp_settings.servers: # Quick return if we have no servers. return ntp or None # Get server_vrf from ntp_settings and configure with the relevant VRF. # Also set relevant local interface. - server_vrf = get(ntp_settings, "server_vrf") + server_vrf = ntp_settings.server_vrf if server_vrf is None: server_vrf = self.shared_utils.default_mgmt_protocol_vrf ntp["local_interface"] = { @@ -54,12 +53,12 @@ def ntp(self: AvdStructuredConfigBase) -> dict | None: } if server_vrf == "use_mgmt_interface_vrf": - has_mgmt_ip = (self.shared_utils.mgmt_ip is not None) or (self.shared_utils.ipv6_mgmt_ip is not None) + has_mgmt_ip = (self.shared_utils.node_config.mgmt_ip is not None) or (self.shared_utils.node_config.ipv6_mgmt_ip is not None) if not has_mgmt_ip: msg = "'ntp_settings.server_vrf' is set to 'use_mgmt_interface_vrf' but this node is missing an 'mgmt_ip'" raise AristaAvdError(msg) # Replacing server_vrf with mgmt_interface_vrf - server_vrf = self.shared_utils.mgmt_interface_vrf + server_vrf = self.inputs.mgmt_interface_vrf ntp["local_interface"] = { "name": self.shared_utils.mgmt_interface, "vrf": server_vrf, @@ -79,8 +78,8 @@ def ntp(self: AvdStructuredConfigBase) -> dict | None: ntp["servers"] = [] # First server is set with preferred first = True - for server in ntp_settings["servers"]: - ntp["servers"].append({**server, "vrf": server_vrf}) + for server in ntp_settings.servers: + ntp["servers"].append({**server._as_dict(), "vrf": server_vrf}) if first: ntp["servers"][-1]["preferred"] = True first = False diff --git a/python-avd/pyavd/_eos_designs/structured_config/base/router_general.py b/python-avd/pyavd/_eos_designs/structured_config/base/router_general.py index 3cb923bfa25..264fdb03a71 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/base/router_general.py +++ b/python-avd/pyavd/_eos_designs/structured_config/base/router_general.py @@ -23,7 +23,7 @@ class RouterGeneralMixin(UtilsMixin): @cached_property def router_general(self: AvdStructuredConfigBase) -> dict | None: - if self.shared_utils.use_router_general_for_router_id: + if self.inputs.use_router_general_for_router_id: return strip_empties_from_dict( { "router_id": { diff --git a/python-avd/pyavd/_eos_designs/structured_config/base/snmp_server.py b/python-avd/pyavd/_eos_designs/structured_config/base/snmp_server.py index 4ec9841975e..b948ba085a0 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/base/snmp_server.py +++ b/python-avd/pyavd/_eos_designs/structured_config/base/snmp_server.py @@ -7,13 +7,16 @@ from hashlib import sha1 from typing import TYPE_CHECKING +from pyavd._eos_cli_config_gen.schema import EosCliConfigGen from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError -from pyavd._utils import get, replace_or_append_item, strip_null_from_data +from pyavd._utils import strip_null_from_data from pyavd.j2filters import natural_sort, snmp_hash from .utils import UtilsMixin if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + from . import AvdStructuredConfigBase @@ -36,8 +39,8 @@ def snmp_server(self: AvdStructuredConfigBase) -> dict | None: we will use snmp_hash filter to create an instance of hashlib HASH corresponding to the auth_type value based on various snmp_settings.users information. """ - source_interfaces_inputs = self._source_interfaces.get("snmp") - snmp_settings = get(self._hostvars, "snmp_settings", {}) + source_interfaces_inputs = self.inputs.source_interfaces.snmp + snmp_settings = self.inputs.snmp_settings if not any([source_interfaces_inputs, snmp_settings]): return None @@ -47,37 +50,38 @@ def snmp_server(self: AvdStructuredConfigBase) -> dict | None: # Pass through most settings with no abstraction. # Use other functions for abstraction. + # return strip_null_from_data( return strip_null_from_data( { "engine_ids": engine_ids, - "contact": snmp_settings.get("contact"), + "contact": snmp_settings.contact, "location": self._snmp_location(snmp_settings), "users": self._snmp_users(snmp_settings, engine_ids), - "hosts": self._snmp_hosts(snmp_settings), - "vrfs": self._snmp_vrfs(snmp_settings), + "hosts": self._snmp_hosts(snmp_settings)._as_list() or None, + "vrfs": self._snmp_vrfs(snmp_settings)._as_list() or None, "local_interfaces": self._snmp_local_interfaces(source_interfaces_inputs), - "communities": snmp_settings.get("communities"), - "ipv4_acls": snmp_settings.get("ipv4_acls"), - "ipv6_acls": snmp_settings.get("ipv6_acls"), - "views": snmp_settings.get("views"), - "groups": snmp_settings.get("groups"), - "traps": snmp_settings.get("traps"), + "communities": snmp_settings.communities._as_list() or None, + "ipv4_acls": snmp_settings.ipv4_acls._as_list() or None, + "ipv6_acls": snmp_settings.ipv6_acls._as_list() or None, + "views": snmp_settings.views._as_list() or None, + "groups": snmp_settings.groups._as_list() or None, + "traps": snmp_settings.traps._as_dict() if snmp_settings.traps.enable else None, }, ) - def _snmp_engine_ids(self: AvdStructuredConfigBase, snmp_settings: dict) -> dict | None: + def _snmp_engine_ids(self: AvdStructuredConfigBase, snmp_settings: EosDesigns.SnmpSettings) -> dict | None: """ Return dict of engine ids if "snmp_settings.compute_local_engineid" is True. Otherwise return None. """ - if snmp_settings.get("compute_local_engineid") is not True: + if not snmp_settings.compute_local_engineid: return None - compute_source = get(snmp_settings, "compute_local_engineid_source", default="hostname_and_ip") + compute_source = snmp_settings.compute_local_engineid_source if compute_source == "hostname_and_ip": # Accepting SonarLint issue: The weak sha1 is not used for encryption. Just to create a unique engine id. - local_engine_id = sha1(f"{self.shared_utils.hostname}{self.shared_utils.mgmt_ip}".encode()).hexdigest() # NOSONAR # noqa: S324 + local_engine_id = sha1(f"{self.shared_utils.hostname}{self.shared_utils.node_config.mgmt_ip}".encode()).hexdigest() # NOSONAR # noqa: S324 elif compute_source == "system_mac": if self.shared_utils.system_mac_address is None: msg = "default_engine_id_from_system_mac: true requires system_mac_address to be set." @@ -91,26 +95,26 @@ def _snmp_engine_ids(self: AvdStructuredConfigBase, snmp_settings: dict) -> dict return {"local": local_engine_id} - def _snmp_location(self: AvdStructuredConfigBase, snmp_settings: dict) -> str | None: + def _snmp_location(self: AvdStructuredConfigBase, snmp_settings: EosDesigns.SnmpSettings) -> str | None: """ Return location if "snmp_settings.location" is True. Otherwise return None. """ - if snmp_settings.get("location") is not True: + if not snmp_settings.location: return None location_elements = [ self.shared_utils.fabric_name, - self.shared_utils.dc_name, - self.shared_utils.pod_name, - self.shared_utils.rack, + self.inputs.dc_name, + self.inputs.pod_name, + self.shared_utils.node_config.rack, self.shared_utils.hostname, ] location_elements = [location for location in location_elements if location not in [None, ""]] return " ".join(location_elements) - def _snmp_users(self: AvdStructuredConfigBase, snmp_settings: dict, engine_ids: dict | None) -> list | None: + def _snmp_users(self: AvdStructuredConfigBase, snmp_settings: EosDesigns.SnmpSettings, engine_ids: dict | None) -> list | None: """ Return users if "snmp_settings.users" is set. @@ -118,74 +122,65 @@ def _snmp_users(self: AvdStructuredConfigBase, snmp_settings: dict, engine_ids: Users will have computed localized keys if configured. """ - if not (users := snmp_settings.get("users")): + if not (users := snmp_settings.users): # Empty list or None return None snmp_users = [] - compute_v3_user_localized_key = ( - (engine_ids is not None) and (engine_ids.get("local") is not None) and (snmp_settings.get("compute_v3_user_localized_key") is True) - ) + compute_v3_user_localized_key = (engine_ids is not None) and (engine_ids.get("local") is not None) and snmp_settings.compute_v3_user_localized_key for user in users: - version = user.get("version") + version = user.version user_dict = { - "name": user.get("name"), - "group": user.get("group"), + "name": user.name, + "group": user.group, "version": version, } if version == "v3": if compute_v3_user_localized_key: user_dict["localized"] = engine_ids["local"] - auth = user.get("auth") - auth_passphrase = user.get("auth_passphrase") - if auth is not None and auth_passphrase is not None: - user_dict["auth"] = auth + if user.auth is not None and user.auth_passphrase is not None: + user_dict["auth"] = user.auth if compute_v3_user_localized_key: - hash_filter = {"passphrase": auth_passphrase, "auth": auth, "engine_id": engine_ids["local"]} + hash_filter = {"passphrase": user.auth_passphrase, "auth": user.auth, "engine_id": engine_ids["local"]} user_dict["auth_passphrase"] = snmp_hash(hash_filter) else: - user_dict["auth_passphrase"] = auth_passphrase + user_dict["auth_passphrase"] = user.auth_passphrase - priv = user.get("priv") - priv_passphrase = user.get("priv_passphrase") - if priv is not None and priv_passphrase is not None: - user_dict["priv"] = priv + if user.priv is not None and user.priv_passphrase is not None: + user_dict["priv"] = user.priv if compute_v3_user_localized_key: - hash_filter.update({"passphrase": priv_passphrase, "priv": priv}) + hash_filter.update({"passphrase": user.priv_passphrase, "priv": user.priv}) user_dict["priv_passphrase"] = snmp_hash(hash_filter) else: - user_dict["priv_passphrase"] = priv_passphrase + user_dict["priv_passphrase"] = user.priv_passphrase snmp_users.append(user_dict) return snmp_users or None - def _snmp_hosts(self: AvdStructuredConfigBase, snmp_settings: dict) -> list | None: + def _snmp_hosts(self: AvdStructuredConfigBase, snmp_settings: EosDesigns.SnmpSettings) -> EosCliConfigGen.SnmpServer.Hosts: """ Return hosts if "snmp_settings.hosts" is set. - Otherwise return None. - Hosts may have management VRFs dynamically set. """ - if not (hosts := snmp_settings.get("hosts")): - # Empty list or None - return None - - snmp_hosts = [] + snmp_hosts = EosCliConfigGen.SnmpServer.Hosts() + if not (hosts := snmp_settings.hosts): + return snmp_hosts - has_mgmt_ip = (self.shared_utils.mgmt_ip is not None) or (self.shared_utils.ipv6_mgmt_ip is not None) + has_mgmt_ip = (self.shared_utils.node_config.mgmt_ip is not None) or (self.shared_utils.node_config.ipv6_mgmt_ip is not None) for host in natural_sort(hosts, "host"): + host: EosDesigns.SnmpSettings.HostsItem vrfs = set() - if (vrf := host.pop("vrf", None)) is not None: + if vrf := host.vrf: vrfs.add(vrf) - if (use_mgmt_interface_vrf := host.pop("use_mgmt_interface_vrf", False)) is True and has_mgmt_ip: - vrfs.add(self.shared_utils.mgmt_interface_vrf) + if (use_mgmt_interface_vrf := host.use_mgmt_interface_vrf) and has_mgmt_ip: + vrfs.add(self.inputs.mgmt_interface_vrf) - if (use_inband_mgmt_vrf := host.pop("use_inband_mgmt_vrf", False)) is True and self.shared_utils.inband_mgmt_interface is not None: + if (use_inband_mgmt_vrf := host.use_inband_mgmt_vrf) and self.shared_utils.inband_mgmt_interface is not None: # self.shared_utils.inband_mgmt_vrf returns None for the default VRF, but here we need "default" to avoid duplicates. vrfs.add(self.shared_utils.inband_mgmt_vrf or "default") @@ -193,18 +188,25 @@ def _snmp_hosts(self: AvdStructuredConfigBase, snmp_settings: dict) -> list | No # If no VRFs are defined (and we are not just ignoring missing mgmt config) vrfs.add("default") + output_host = host._cast_as(EosCliConfigGen.SnmpServer.HostsItem, ignore_extra_keys=True) + # Ensure default VRF is added first if "default" in vrfs: vrfs.remove("default") # Add host without VRF field - snmp_hosts.append(host) + add_host = output_host._deepcopy() + delattr(add_host, "vrf") + snmp_hosts.append(add_host) # Add host with VRF field. - snmp_hosts.extend({**host, "vrf": vrf} for vrf in natural_sort(vrfs)) + for vrf in natural_sort(vrfs): + add_host = output_host._deepcopy() + add_host.vrf = vrf + snmp_hosts.append(add_host) - return snmp_hosts or None + return snmp_hosts - def _snmp_local_interfaces(self: AvdStructuredConfigBase, source_interfaces_inputs: dict | None) -> list | None: + def _snmp_local_interfaces(self: AvdStructuredConfigBase, source_interfaces_inputs: EosDesigns.SourceInterfaces.Snmp) -> list | None: """ Return local_interfaces if "source_interfaces.snmp" is set. @@ -214,14 +216,10 @@ def _snmp_local_interfaces(self: AvdStructuredConfigBase, source_interfaces_inpu # Empty dict or None return None - local_interfaces = self._build_source_interfaces( - source_interfaces_inputs.get("mgmt_interface", False), - source_interfaces_inputs.get("inband_mgmt_interface", False), - "SNMP", - ) + local_interfaces = self._build_source_interfaces(source_interfaces_inputs.mgmt_interface, source_interfaces_inputs.inband_mgmt_interface, "SNMP") return local_interfaces or None - def _snmp_vrfs(self: AvdStructuredConfigBase, snmp_settings: dict | None) -> list | None: + def _snmp_vrfs(self: AvdStructuredConfigBase, snmp_settings: EosDesigns.SnmpSettings) -> EosDesigns.SnmpSettings.Vrfs: """ Return list of dicts for enabling/disabling SNMP for VRFs. @@ -229,28 +227,15 @@ def _snmp_vrfs(self: AvdStructuredConfigBase, snmp_settings: dict | None) -> lis - vrfs - enable_mgmt_interface_vrf - enable_inband_mgmt_vrf - Otherwise return None. """ - if snmp_settings is None: - return None + has_mgmt_ip = (self.shared_utils.node_config.mgmt_ip is not None) or (self.shared_utils.node_config.ipv6_mgmt_ip is not None) - has_mgmt_ip = (self.shared_utils.mgmt_ip is not None) or (self.shared_utils.ipv6_mgmt_ip is not None) + vrfs = snmp_settings.vrfs._deepcopy() + if has_mgmt_ip and (enable_mgmt_interface_vrf := snmp_settings.enable_mgmt_interface_vrf) is not None: + vrfs.append(EosCliConfigGen.SnmpServer.VrfsItem(name=self.inputs.mgmt_interface_vrf, enable=enable_mgmt_interface_vrf)) - # Initialize a set with all vrfs (Catching None value with or []) - vrfs = get(snmp_settings, "vrfs", default=[]) - if has_mgmt_ip and (enable_mgmt_interface_vrf := snmp_settings.get("enable_mgmt_interface_vrf")) is not None: - vrf = { - "name": self.shared_utils.mgmt_interface_vrf, - "enable": enable_mgmt_interface_vrf, - } - replace_or_append_item(vrfs, "name", vrf) - - if (enable_inband_mgmt_vrf := snmp_settings.get("enable_inband_mgmt_vrf")) is not None and self.shared_utils.inband_mgmt_interface is not None: + if (enable_inband_mgmt_vrf := snmp_settings.enable_inband_mgmt_vrf) is not None and self.shared_utils.inband_mgmt_interface is not None: # self.shared_utils.inband_mgmt_vrf returns None for the default VRF, but here we need "default" to avoid duplicates. - vrf = { - "name": self.shared_utils.inband_mgmt_vrf or "default", - "enable": enable_inband_mgmt_vrf, - } - replace_or_append_item(vrfs, "name", vrf) + vrfs.append(EosCliConfigGen.SnmpServer.VrfsItem(name=self.shared_utils.inband_mgmt_vrf or "default", enable=enable_inband_mgmt_vrf)) - return natural_sort(vrfs, "name") or None + return vrfs._natural_sorted() diff --git a/python-avd/pyavd/_eos_designs/structured_config/base/utils.py b/python-avd/pyavd/_eos_designs/structured_config/base/utils.py index 52c4f6089e5..6117ce47511 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/base/utils.py +++ b/python-avd/pyavd/_eos_designs/structured_config/base/utils.py @@ -7,7 +7,6 @@ from typing import TYPE_CHECKING from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError -from pyavd._utils import get if TYPE_CHECKING: from . import AvdStructuredConfigBase @@ -20,10 +19,6 @@ class UtilsMixin: Class should only be used as Mixin to a AvdStructuredConfig class or other Mixins. """ - @cached_property - def _source_interfaces(self: AvdStructuredConfigBase) -> dict: - return get(self._hostvars, "source_interfaces", default={}) - def _build_source_interfaces(self: AvdStructuredConfigBase, include_mgmt_interface: bool, include_inband_mgmt_interface: bool, error_context: str) -> list: """ Return list of source interfaces with VRFs. @@ -35,14 +30,14 @@ def _build_source_interfaces(self: AvdStructuredConfigBase, include_mgmt_interfa source_interfaces = [] if include_mgmt_interface: - if (self.shared_utils.mgmt_ip is None) and (self.shared_utils.ipv6_mgmt_ip is None): + if (self.shared_utils.node_config.mgmt_ip is None) and (self.shared_utils.node_config.ipv6_mgmt_ip is None): msg = f"Unable to configure {error_context} source-interface since 'mgmt_ip' or 'ipv6_mgmt_ip' are not set." raise AristaAvdInvalidInputsError(msg) # mgmt_interface is always set (defaults to "Management1") so no need for error handling missing interface. source_interface = {"name": self.shared_utils.mgmt_interface} - if self.shared_utils.mgmt_interface_vrf not in [None, "default"]: - source_interface["vrf"] = self.shared_utils.mgmt_interface_vrf + if self.inputs.mgmt_interface_vrf not in [None, "default"]: + source_interface["vrf"] = self.inputs.mgmt_interface_vrf source_interfaces.append(source_interface) if include_inband_mgmt_interface: @@ -71,7 +66,7 @@ def _router_bgp_redistribute_routes(self: AvdStructuredConfigBase) -> dict | Non if not (self.shared_utils.underlay_bgp or self.shared_utils.is_wan_router or self.shared_utils.l3_interfaces_bgp_neighbors): return None - if self.shared_utils.overlay_routing_protocol != "none" and self.shared_utils.underlay_filter_redistribute_connected: + if self.shared_utils.overlay_routing_protocol != "none" and self.inputs.underlay_filter_redistribute_connected: # Use route-map for redistribution return {"connected": {"enabled": True, "route_map": "RM-CONN-2-BGP"}} diff --git a/python-avd/pyavd/_eos_designs/structured_config/connected_endpoints/ethernet_interfaces.py b/python-avd/pyavd/_eos_designs/structured_config/connected_endpoints/ethernet_interfaces.py index 73cbcf27e8e..eab9da40a17 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/connected_endpoints/ethernet_interfaces.py +++ b/python-avd/pyavd/_eos_designs/structured_config/connected_endpoints/ethernet_interfaces.py @@ -4,12 +4,12 @@ from __future__ import annotations import re -from collections import ChainMap from functools import cached_property from typing import TYPE_CHECKING +from pyavd._eos_designs.schema import EosDesigns from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError -from pyavd._utils import append_if_not_duplicate, default, get, replace_or_append_item, strip_null_from_data +from pyavd._utils import Undefined, append_if_not_duplicate, replace_or_append_item, strip_null_from_data from pyavd.api.interface_descriptions import InterfaceDescriptionData from pyavd.j2filters import range_expand @@ -43,25 +43,26 @@ def ethernet_interfaces(self: AvdStructuredConfigConnectedEndpoints) -> list | N non_overwritable_ethernet_interfaces = [] for network_port in self._filtered_network_ports: - connected_endpoint = { - "name": network_port.get("endpoint"), - "type": "network_port", - } - for ethernet_interface_name in range_expand(network_port["switch_ports"]): + connected_endpoint = EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem(name=network_port.endpoint or Undefined) + connected_endpoint._type = "network_port" + network_port_as_adapter = network_port._cast_as( + EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem, ignore_extra_keys=True + ) + network_port_as_adapter._context = network_port._context + for ethernet_interface_name in range_expand(network_port.switch_ports): # Override switches and switch_ports to only render for a single interface - tmp_network_port = ChainMap( - { - "switch_ports": [ethernet_interface_name], - "switches": [self.shared_utils.hostname], - }, - network_port, + network_port_as_adapter.switch_ports = EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem.SwitchPorts( + [ethernet_interface_name] + ) + network_port_as_adapter.switches = EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem.Switches( + [self.shared_utils.hostname] ) - ethernet_interface = self._get_ethernet_interface_cfg(tmp_network_port, 0, connected_endpoint) + ethernet_interface = self._get_ethernet_interface_cfg(network_port_as_adapter, 0, connected_endpoint) replace_or_append_item(ethernet_interfaces, "name", ethernet_interface) for connected_endpoint in self._filtered_connected_endpoints: - for adapter in connected_endpoint["adapters"]: - for node_index, node_name in enumerate(adapter["switches"]): + for adapter in connected_endpoint.adapters: + for node_index, node_name in enumerate(adapter.switches): if node_name != self.shared_utils.hostname: continue @@ -82,9 +83,12 @@ def ethernet_interfaces(self: AvdStructuredConfigConnectedEndpoints) -> list | N return None def _update_ethernet_interface_cfg( - self: AvdStructuredConfigConnectedEndpoints, adapter: dict | ChainMap, ethernet_interface: dict, connected_endpoint: dict + self: AvdStructuredConfigConnectedEndpoints, + adapter: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem, + ethernet_interface: dict, + connected_endpoint: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem, ) -> dict: - if (vlans := adapter.get("vlans")) is not None and adapter.get("mode") in ["access", "dot1q-tunnel"]: + if (vlans := adapter.vlans) is not None and adapter.mode in ["access", "dot1q-tunnel"]: try: # For access ports we use the 'vlans' field (str) as 'access_vlan' (int). Attempting to convert. vlans = int(vlans) @@ -97,120 +101,115 @@ def _update_ethernet_interface_cfg( ethernet_interface.update( { - "mtu": adapter.get("mtu") if self.shared_utils.platform_settings_feature_support_per_interface_mtu else None, - "l2_mtu": adapter.get("l2_mtu"), - "l2_mru": adapter.get("l2_mru"), + "mtu": adapter.mtu if self.shared_utils.platform_settings.feature_support.per_interface_mtu else None, + "l2_mtu": adapter.l2_mtu, + "l2_mru": adapter.l2_mru, "switchport": { "enabled": True, - "mode": adapter.get("mode"), + "mode": adapter.mode, "trunk": { - "allowed_vlan": vlans if adapter.get("mode") == "trunk" else None, + "allowed_vlan": vlans if adapter.mode == "trunk" else None, "groups": self._get_adapter_trunk_groups(adapter, connected_endpoint), - "native_vlan_tag": adapter.get("native_vlan_tag"), - "native_vlan": adapter.get("native_vlan"), + "native_vlan_tag": adapter.native_vlan_tag, + "native_vlan": adapter.native_vlan, }, - "access_vlan": vlans if adapter.get("mode") in ["access", "dot1q-tunnel"] else None, + "access_vlan": vlans if adapter.mode in ["access", "dot1q-tunnel"] else None, "phone": self._get_adapter_phone(adapter, connected_endpoint), }, - "spanning_tree_portfast": adapter.get("spanning_tree_portfast"), - "spanning_tree_bpdufilter": adapter.get("spanning_tree_bpdufilter"), - "spanning_tree_bpduguard": adapter.get("spanning_tree_bpduguard"), + "spanning_tree_portfast": adapter.spanning_tree_portfast, + "spanning_tree_bpdufilter": adapter.spanning_tree_bpdufilter, + "spanning_tree_bpduguard": adapter.spanning_tree_bpduguard, "storm_control": self._get_adapter_storm_control(adapter), "ptp": self._get_adapter_ptp(adapter), - "service_profile": adapter.get("qos_profile"), + "service_profile": adapter.qos_profile, "sflow": self._get_adapter_sflow(adapter), - "flow_tracker": self._get_adapter_flow_tracking(adapter), + "flow_tracker": self.shared_utils.get_flow_tracker(adapter.flow_tracking), "link_tracking_groups": self._get_adapter_link_tracking_groups(adapter), }, ) return strip_null_from_data(ethernet_interface, strip_values_tuple=(None, "", {})) - def _get_ethernet_interface_cfg(self: AvdStructuredConfigConnectedEndpoints, adapter: dict | ChainMap, node_index: int, connected_endpoint: dict) -> dict: + def _get_ethernet_interface_cfg( + self: AvdStructuredConfigConnectedEndpoints, + adapter: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem, + node_index: int, + connected_endpoint: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem, + ) -> dict: """Return structured_config for one ethernet_interface.""" - peer = connected_endpoint["name"] - endpoint_ports: list = default( - adapter.get("endpoint_ports"), - [], - ) + peer = connected_endpoint.name + endpoint_ports = adapter.endpoint_ports peer_interface = endpoint_ports[node_index] if node_index < len(endpoint_ports) else None - default_channel_group_id = int("".join(re.findall(r"\d", adapter["switch_ports"][0]))) - channel_group_id = get(adapter, "port_channel.channel_id", default=default_channel_group_id) + default_channel_group_id = int("".join(re.findall(r"\d", adapter.switch_ports[0]))) + channel_group_id = adapter.port_channel.channel_id or default_channel_group_id short_esi = self._get_short_esi(adapter, channel_group_id) - port_channel_mode = get(adapter, "port_channel.mode") + port_channel_mode = adapter.port_channel.mode # check lengths of lists - nodes_length = len(adapter["switches"]) - if len(adapter["switch_ports"]) != nodes_length or ("descriptions" in adapter and len(adapter["descriptions"]) != nodes_length): + nodes_length = len(adapter.switches) + if len(adapter.switch_ports) != nodes_length or (adapter.descriptions and len(adapter.descriptions) != nodes_length): msg = ( f"Length of lists 'switches', 'switch_ports', and 'descriptions' (if used) must match for adapter. Check configuration for {peer}, adapter" - f" switch_ports {adapter['switch_ports']}." - ) - raise AristaAvdError( - msg, + f" switch_ports {adapter.switch_ports._as_list()}." ) + raise AristaAvdError(msg) # if 'descriptions' is set, it is preferred - if (interface_descriptions := adapter.get("descriptions")) is not None: - interface_description = interface_descriptions[node_index] - else: - interface_description = get(adapter, "description") + interface_description = adapter.descriptions[node_index] if adapter.descriptions else adapter.description # Common ethernet_interface settings ethernet_interface = { - "name": adapter["switch_ports"][node_index], + "name": adapter.switch_ports[node_index], "peer": peer, "peer_interface": peer_interface, - "peer_type": connected_endpoint["type"], - "port_profile": adapter.get("profile"), + "peer_type": connected_endpoint._type, + "port_profile": adapter.profile, "description": self.shared_utils.interface_descriptions.connected_endpoints_ethernet_interface( InterfaceDescriptionData( shared_utils=self.shared_utils, - interface=adapter["switch_ports"][node_index], + interface=adapter.switch_ports[node_index], peer=peer, peer_interface=peer_interface, - peer_type=connected_endpoint["type"], + peer_type=connected_endpoint._type, description=interface_description, port_channel_id=channel_group_id if port_channel_mode is not None else None, ), ) or None, - "speed": adapter.get("speed"), - "shutdown": not adapter.get("enabled", True), - "validate_state": None if adapter.get("validate_state", True) else False, - "dot1x": adapter.get("dot1x"), + "speed": adapter.speed, + "shutdown": not (adapter.enabled if adapter.enabled is not None else True), + "validate_state": None if (adapter.validate_state if adapter.validate_state is not None else True) else False, + "dot1x": adapter.dot1x._as_dict() or None, "poe": self._get_adapter_poe(adapter), - "eos_cli": adapter.get("raw_eos_cli"), - "struct_cfg": adapter.get("structured_config"), + "eos_cli": adapter.raw_eos_cli, + "struct_cfg": adapter.structured_config._as_dict(strip_values=()), } # Port-channel member - if port_channel_mode is not None: - ethernet_interface["channel_group"] = { - "id": channel_group_id, - "mode": port_channel_mode, - } + if adapter.port_channel.mode: + ethernet_interface["channel_group"] = {"id": channel_group_id, "mode": adapter.port_channel.mode} - if get(adapter, "port_channel.lacp_fallback.mode") == "static": + if (lacp_fallback_mode := adapter.port_channel.lacp_fallback.mode) == "static": ethernet_interface["lacp_port_priority"] = 8192 if node_index == 0 else 32768 - elif get(adapter, "port_channel.lacp_fallback.mode") == "individual": + elif lacp_fallback_mode == "individual": # if fallback is set to individual a profile has to be defined - if (profile_name := get(adapter, "port_channel.lacp_fallback.individual.profile")) is None: + if (profile_name := adapter.port_channel.lacp_fallback.individual.profile) is None: msg = ( "A Port-channel which is set to lacp fallback mode 'individual' must have a 'profile' defined. Profile definition is missing for" - f" the connected endpoint with the name '{connected_endpoint['name']}'." + f" the connected endpoint with the name '{connected_endpoint.name}'." ) raise AristaAvdInvalidInputsError(msg) - profile = self.shared_utils.get_merged_port_profile(profile_name, context=f"{adapter['context']}.port_channel.lacp_fallback.individual") - profile["context"] = adapter["context"] - + profile = self.shared_utils.get_merged_port_profile(profile_name, context=f"{adapter._context}.port_channel.lacp_fallback.individual")._cast_as( + EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem + ) + profile._context = adapter._context ethernet_interface = self._update_ethernet_interface_cfg(profile, ethernet_interface, connected_endpoint) - if port_channel_mode != "on" and get(adapter, "port_channel.lacp_timer") is not None: + if adapter.port_channel.mode != "on" and adapter.port_channel.lacp_timer.mode is not None: ethernet_interface["lacp_timer"] = { - "mode": get(adapter, "port_channel.lacp_timer.mode"), - "multiplier": get(adapter, "port_channel.lacp_timer.multiplier"), + "mode": adapter.port_channel.lacp_timer.mode, + "multiplier": adapter.port_channel.lacp_timer.multiplier, } else: @@ -225,7 +224,7 @@ def _get_ethernet_interface_cfg(self: AvdStructuredConfigConnectedEndpoints, ada ) # More common ethernet_interface settings - if (flowcontrol_received := get(adapter, "flowcontrol.received")) is not None: - ethernet_interface["flowcontrol"] = {"received": flowcontrol_received} + if adapter.flowcontrol.received: + ethernet_interface["flowcontrol"] = {"received": adapter.flowcontrol.received} return strip_null_from_data(ethernet_interface, strip_values_tuple=(None, "")) diff --git a/python-avd/pyavd/_eos_designs/structured_config/connected_endpoints/monitor_sessions.py b/python-avd/pyavd/_eos_designs/structured_config/connected_endpoints/monitor_sessions.py index 4cfd92f7205..7eb5d0bf302 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/connected_endpoints/monitor_sessions.py +++ b/python-avd/pyavd/_eos_designs/structured_config/connected_endpoints/monitor_sessions.py @@ -8,12 +8,14 @@ from typing import TYPE_CHECKING from pyavd._errors import AristaAvdInvalidInputsError -from pyavd._utils import append_if_not_duplicate, get, groupby, merge, strip_null_from_data +from pyavd._utils import append_if_not_duplicate, groupby_obj, strip_null_from_data from pyavd.j2filters import range_expand from .utils import UtilsMixin if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + from . import AvdStructuredConfigConnectedEndpoints @@ -32,37 +34,38 @@ def monitor_sessions(self: AvdStructuredConfigConnectedEndpoints) -> list | None monitor_sessions = [] - for session_name, session_configs in groupby(self._monitor_session_configs, "name"): + for session_name, session_configs in groupby_obj(self._monitor_session_configs, "name"): # Convert iterator to list since we can only access it once. session_configs_list = list(session_configs) - merged_settings = merge({}, session_configs_list, destructive_merge=False) + merged_settings = session_configs_list[0]._deepcopy() + for session_config in session_configs_list[1:]: + merged_settings._deepmerge(session_config) - if get(merged_settings, "session_settings.access_group"): + if merged_settings.session_settings.access_group: for session in session_configs_list: - if get(session, "source_settings.access_group"): + if session.source_settings.access_group: msg = ( f"Cannot set an ACL for both `session_settings` and `source_settings`" - f" under the monitor session '{session['name']}' for {session['context']}." + f" under the monitor session '{session.name}' for {session._context}." ) raise AristaAvdInvalidInputsError(msg) monitor_session = { "name": session_name, "sources": [], - "destinations": [session["interface"] for session in session_configs_list if session.get("role") == "destination"], + "destinations": [session._interface for session in session_configs_list if session.role == "destination"], } - source_sessions = [session for session in session_configs_list if session.get("role") == "source"] + source_sessions = [session for session in session_configs_list if session.role == "source"] for session in source_sessions: source = { - "name": session["interface"], - "direction": get(session, "source_settings.direction"), + "name": session._interface, + "direction": session.source_settings.direction, } - - if (access_group := get(session, "source_settings.access_group")) is not None: + if session.source_settings.access_group.name is not None: source["access_group"] = { - "type": access_group.get("type"), - "name": access_group.get("name"), - "priority": access_group.get("priority"), + "type": session.source_settings.access_group.type, + "name": session.source_settings.access_group.name, + "priority": session.source_settings.access_group.priority, } append_if_not_duplicate( list_of_dicts=monitor_session["sources"], @@ -72,8 +75,8 @@ def monitor_sessions(self: AvdStructuredConfigConnectedEndpoints) -> list | None context_keys=["name"], ) - if (session_settings := merged_settings.get("session_settings")) is not None: - monitor_session.update(session_settings) + if session_settings := merged_settings.session_settings: + monitor_session.update(session_settings._as_dict()) monitor_sessions.append(monitor_session) @@ -83,66 +86,64 @@ def monitor_sessions(self: AvdStructuredConfigConnectedEndpoints) -> list | None return None @cached_property - def _monitor_session_configs(self: AvdStructuredConfigConnectedEndpoints) -> list: + def _monitor_session_configs( + self: AvdStructuredConfigConnectedEndpoints, + ) -> list[EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem.MonitorSessionsItem]: """Return list of monitor session configs extracted from every interface.""" monitor_session_configs = [] for connected_endpoint in self._filtered_connected_endpoints: - for adapter in connected_endpoint["adapters"]: - if "monitor_sessions" not in adapter: + for adapter in connected_endpoint.adapters: + if not adapter.monitor_sessions: continue # Monitor session on Port-channel interface - if get(adapter, "port_channel.mode") is not None: - default_channel_group_id = int("".join(re.findall(r"\d", adapter["switch_ports"][0]))) - channel_group_id = get(adapter, "port_channel.channel_id", default=default_channel_group_id) + if adapter.port_channel.mode: + default_channel_group_id = int("".join(re.findall(r"\d", adapter.switch_ports[0]))) + channel_group_id = adapter.port_channel.channel_id or default_channel_group_id port_channel_interface_name = f"Port-Channel{channel_group_id}" - monitor_session_configs.extend( - [ - dict(monitor_session, interface=port_channel_interface_name, context=adapter["context"]) - for monitor_session in adapter["monitor_sessions"] - ], - ) + for monitor_session in adapter.monitor_sessions: + per_interface_monitor_session = monitor_session._deepcopy() + per_interface_monitor_session._interface = port_channel_interface_name + per_interface_monitor_session._context = adapter._context + monitor_session_configs.append(per_interface_monitor_session) continue # Monitor session on Ethernet interface - for node_index, node_name in enumerate(adapter["switches"]): + for node_index, node_name in enumerate(adapter.switches): if node_name != self.shared_utils.hostname: continue - ethernet_interface_name = adapter["switch_ports"][node_index] - monitor_session_configs.extend( - [ - dict(monitor_session, interface=ethernet_interface_name, context=adapter["context"]) - for monitor_session in adapter["monitor_sessions"] - ], - ) + ethernet_interface_name = adapter.switch_ports[node_index] + for monitor_session in adapter.monitor_sessions: + per_interface_monitor_session = monitor_session._deepcopy() + per_interface_monitor_session._interface = ethernet_interface_name + per_interface_monitor_session._context = adapter._context + monitor_session_configs.append(per_interface_monitor_session) for network_port in self._filtered_network_ports: - if "monitor_sessions" not in network_port: + if not network_port.monitor_sessions: continue - for ethernet_interface_name in range_expand(network_port["switch_ports"]): + for ethernet_interface_name in range_expand(network_port.switch_ports): # Monitor session on Port-channel interface - if get(network_port, "port_channel.mode") is not None: + if network_port.port_channel and network_port.port_channel.mode is not None: default_channel_group_id = int("".join(re.findall(r"\d", ethernet_interface_name))) - channel_group_id = get(network_port, "port_channel.channel_id", default=default_channel_group_id) + channel_group_id = network_port.port_channel.channel_id or default_channel_group_id port_channel_interface_name = f"Port-Channel{channel_group_id}" - monitor_session_configs.extend( - [ - dict(monitor_session, interface=port_channel_interface_name, context=network_port["context"]) - for monitor_session in network_port["monitor_sessions"] - ], - ) + for monitor_session in network_port.monitor_sessions: + per_interface_monitor_session = monitor_session._deepcopy() + per_interface_monitor_session._interface = port_channel_interface_name + per_interface_monitor_session._context = network_port._context + monitor_session_configs.append(per_interface_monitor_session) continue # Monitor session on Ethernet interface - monitor_session_configs.extend( - [ - dict(monitor_session, interface=ethernet_interface_name, context=network_port["context"]) - for monitor_session in network_port["monitor_sessions"] - ], - ) + for monitor_session in network_port.monitor_sessions: + per_interface_monitor_session = monitor_session._deepcopy() + per_interface_monitor_session._interface = ethernet_interface_name + per_interface_monitor_session._context = network_port._context + monitor_session_configs.append(per_interface_monitor_session) return monitor_session_configs diff --git a/python-avd/pyavd/_eos_designs/structured_config/connected_endpoints/port_channel_interfaces.py b/python-avd/pyavd/_eos_designs/structured_config/connected_endpoints/port_channel_interfaces.py index 77459bbab4b..51a6697b107 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/connected_endpoints/port_channel_interfaces.py +++ b/python-avd/pyavd/_eos_designs/structured_config/connected_endpoints/port_channel_interfaces.py @@ -4,12 +4,12 @@ from __future__ import annotations import re -from collections import ChainMap from functools import cached_property from typing import TYPE_CHECKING +from pyavd._eos_designs.schema import EosDesigns from pyavd._errors import AristaAvdInvalidInputsError -from pyavd._utils import append_if_not_duplicate, get, short_esi_to_route_target, strip_null_from_data +from pyavd._utils import Undefined, append_if_not_duplicate, get, short_esi_to_route_target, strip_null_from_data from pyavd.api.interface_descriptions import InterfaceDescriptionData from pyavd.j2filters import range_expand @@ -37,12 +37,12 @@ def port_channel_interfaces(self: AvdStructuredConfigConnectedEndpoints) -> list """ port_channel_interfaces = [] for connected_endpoint in self._filtered_connected_endpoints: - for adapter in connected_endpoint["adapters"]: - if get(adapter, "port_channel.mode") is None: + for adapter in connected_endpoint.adapters: + if not adapter.port_channel or not adapter.port_channel.mode: continue - default_channel_group_id = int("".join(re.findall(r"\d", adapter["switch_ports"][0]))) - channel_group_id = get(adapter, "port_channel.channel_id", default=default_channel_group_id) + default_channel_group_id = int("".join(re.findall(r"\d", adapter.switch_ports[0]))) + channel_group_id = adapter.port_channel.channel_id or default_channel_group_id port_channel_interface_name = f"Port-Channel{channel_group_id}" port_channel_config = self._get_port_channel_interface_cfg(adapter, port_channel_interface_name, channel_group_id, connected_endpoint) @@ -54,14 +54,11 @@ def port_channel_interfaces(self: AvdStructuredConfigConnectedEndpoints) -> list context_keys=["name"], ) - if (subinterfaces := get(adapter, "port_channel.subinterfaces")) is None: - continue - - for subinterface in subinterfaces: - if "number" not in subinterface: + for subinterface in adapter.port_channel.subinterfaces: + if not subinterface.number: continue - port_channel_subinterface_name = f"Port-Channel{channel_group_id}.{subinterface['number']}" + port_channel_subinterface_name = f"Port-Channel{channel_group_id}.{subinterface.number}" port_channel_subinterface_config = self._get_port_channel_subinterface_cfg( subinterface, adapter, @@ -77,31 +74,34 @@ def port_channel_interfaces(self: AvdStructuredConfigConnectedEndpoints) -> list ) for network_port in self._filtered_network_ports: - if get(network_port, "port_channel.mode") is None: + if not network_port.port_channel.mode: continue - connected_endpoint = { - "name": network_port.get("endpoint"), - "type": "network_port", - } - for ethernet_interface_name in range_expand(network_port["switch_ports"]): + connected_endpoint = EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem(name=network_port.endpoint or Undefined) + connected_endpoint._type = "network_port" + network_port_as_adapter = network_port._cast_as( + EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem, ignore_extra_keys=True + ) + for ethernet_interface_name in range_expand(network_port.switch_ports): # Override switches and switch_ports to only render for a single interface # The blank extra switch is only inserted to work around port_channel validations # This also means that port-channels defined with network_ports data model will be single-port per switch. # Caveat: "short_esi: auto" and "designated_forwarder_algorithm: auto" will not work correctly. - tmp_network_port = ChainMap( - { - "switch_ports": [ethernet_interface_name, ""], - "switches": [self.shared_utils.hostname, ""], - }, - network_port, + network_port_as_adapter.switch_ports = EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem.SwitchPorts( + [ethernet_interface_name, ""] + ) + network_port_as_adapter.switches = EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem.Switches( + [self.shared_utils.hostname, ""] ) default_channel_group_id = int("".join(re.findall(r"\d", ethernet_interface_name))) - channel_group_id = get(tmp_network_port, "port_channel.channel_id", default=default_channel_group_id) + channel_group_id = network_port_as_adapter.port_channel.channel_id or default_channel_group_id port_channel_interface_name = f"Port-Channel{channel_group_id}" - port_channel_config = self._get_port_channel_interface_cfg(tmp_network_port, port_channel_interface_name, channel_group_id, connected_endpoint) + + port_channel_config = self._get_port_channel_interface_cfg( + network_port_as_adapter, port_channel_interface_name, channel_group_id, connected_endpoint + ) append_if_not_duplicate( list_of_dicts=port_channel_interfaces, primary_key="name", @@ -117,24 +117,21 @@ def port_channel_interfaces(self: AvdStructuredConfigConnectedEndpoints) -> list def _get_port_channel_interface_cfg( self: AvdStructuredConfigConnectedEndpoints, - adapter: dict | ChainMap, + adapter: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem, port_channel_interface_name: str, channel_group_id: int, - connected_endpoint: dict, + connected_endpoint: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem, ) -> dict: """Return structured_config for one port_channel_interface.""" - peer = connected_endpoint["name"] - adapter_description = get(adapter, "description") - port_channel_description = get(adapter, "port_channel.description") - port_channel_mode = get(adapter, "port_channel.mode") - peer_interface = get(adapter, "port_channel.endpoint_port_channel") - node_index = adapter["switches"].index(self.shared_utils.hostname) + peer = connected_endpoint.name + adapter_description = adapter.description + port_channel_description = adapter.port_channel.description + port_channel_mode = adapter.port_channel.mode + peer_interface = adapter.port_channel.endpoint_port_channel + node_index = adapter.switches.index(self.shared_utils.hostname) # if 'descriptions' is set, it is preferred - if (interface_descriptions := adapter.get("descriptions")) is not None: - adapter_description = interface_descriptions[node_index] - else: - adapter_description = adapter.get("description") + adapter_description = interface_descriptions[node_index] if (interface_descriptions := adapter.descriptions) else adapter.description # Common port_channel_interface settings port_channel_interface = { @@ -145,29 +142,29 @@ def _get_port_channel_interface_cfg( interface=port_channel_interface_name, peer=peer, peer_interface=peer_interface, - peer_type=connected_endpoint["type"], + peer_type=connected_endpoint._type, description=adapter_description, port_channel_id=channel_group_id, port_channel_description=port_channel_description, ), ), - "shutdown": not get(adapter, "port_channel.enabled", default=True), - "mtu": adapter.get("mtu") if self.shared_utils.platform_settings_feature_support_per_interface_mtu else None, - "service_profile": adapter.get("qos_profile"), + "shutdown": not (adapter.port_channel.enabled if adapter.port_channel.enabled is not None else True), + "mtu": adapter.mtu if self.shared_utils.platform_settings.feature_support.per_interface_mtu else None, + "service_profile": adapter.qos_profile, "link_tracking_groups": self._get_adapter_link_tracking_groups(adapter), "ptp": self._get_adapter_ptp(adapter), "sflow": self._get_adapter_sflow(adapter), - "flow_tracker": self._get_adapter_flow_tracking(adapter), - "validate_state": None if adapter.get("validate_state", True) else False, - "eos_cli": get(adapter, "port_channel.raw_eos_cli"), - "struct_cfg": get(adapter, "port_channel.structured_config"), + "flow_tracker": self.shared_utils.get_flow_tracker(adapter.flow_tracking), + "validate_state": None if (adapter.validate_state if adapter.validate_state is not None else True) else False, + "eos_cli": adapter.port_channel.raw_eos_cli, + "struct_cfg": adapter.port_channel.structured_config._as_dict(strip_values=()) or None, } - if get(adapter, "port_channel.subinterfaces"): + if adapter.port_channel.subinterfaces: port_channel_interface.update({"switchport": {"enabled": False}}) else: # switchport - if (vlans := adapter.get("vlans")) is not None and adapter.get("mode") in ["access", "dot1q-tunnel"]: + if (vlans := adapter.vlans) is not None and adapter.mode in ["access", "dot1q-tunnel"]: try: # For access ports we use the 'vlans' field (str) as 'access_vlan' (int). Attempting to convert. vlans = int(vlans) @@ -182,21 +179,21 @@ def _get_port_channel_interface_cfg( { "switchport": { "enabled": True, - "mode": adapter.get("mode"), + "mode": adapter.mode, "trunk": { - "allowed_vlan": vlans if adapter.get("mode") == "trunk" else None, + "allowed_vlan": vlans if adapter.mode == "trunk" else None, "groups": self._get_adapter_trunk_groups(adapter, connected_endpoint), - "native_vlan_tag": adapter.get("native_vlan_tag"), - "native_vlan": adapter.get("native_vlan"), + "native_vlan_tag": adapter.native_vlan_tag, + "native_vlan": adapter.native_vlan, }, "phone": self._get_adapter_phone(adapter, connected_endpoint), - "access_vlan": vlans if adapter.get("mode") in ["access", "dot1q-tunnel"] else None, + "access_vlan": vlans if adapter.mode in ["access", "dot1q-tunnel"] else None, }, - "l2_mtu": adapter.get("l2_mtu"), - "l2_mru": adapter.get("l2_mru"), - "spanning_tree_portfast": adapter.get("spanning_tree_portfast"), - "spanning_tree_bpdufilter": adapter.get("spanning_tree_bpdufilter"), - "spanning_tree_bpduguard": adapter.get("spanning_tree_bpduguard"), + "l2_mtu": adapter.l2_mtu, + "l2_mru": adapter.l2_mru, + "spanning_tree_portfast": adapter.spanning_tree_portfast, + "spanning_tree_bpdufilter": adapter.spanning_tree_bpdufilter, + "spanning_tree_bpduguard": adapter.spanning_tree_bpduguard, "storm_control": self._get_adapter_storm_control(adapter), }, ) @@ -208,17 +205,17 @@ def _get_port_channel_interface_cfg( port_channel_interface["lacp_id"] = short_esi.replace(":", ".") # Set MLAG ID on port-channel if connection is multi-homed and this switch is running MLAG - elif self.shared_utils.mlag and len(set(adapter["switches"])) > 1: - if get(port_channel_interface, "ptp.enable") is True and get(adapter, "port_channel.ptp_mpass") is True: + elif self.shared_utils.mlag and len(set(adapter.switches)) > 1: + if get(port_channel_interface, "ptp.enable") is True and adapter.port_channel.ptp_mpass: port_channel_interface["ptp"]["mpass"] = True port_channel_interface["mlag"] = channel_group_id # LACP Fallback - if port_channel_mode in ["active", "passive"] and (lacp_fallback_mode := get(adapter, "port_channel.lacp_fallback.mode")) in ["static", "individual"]: + if port_channel_mode in ["active", "passive"] and (lacp_fallback_mode := adapter.port_channel.lacp_fallback.mode) in ["static", "individual"]: port_channel_interface.update( { "lacp_fallback_mode": lacp_fallback_mode, - "lacp_fallback_timeout": get(adapter, "port_channel.lacp_fallback.timeout", default=90), + "lacp_fallback_timeout": adapter.port_channel.lacp_fallback.timeout or 90, }, ) @@ -226,8 +223,8 @@ def _get_port_channel_interface_cfg( def _get_port_channel_subinterface_cfg( self: AvdStructuredConfigConnectedEndpoints, - subinterface: dict, - adapter: dict, + subinterface: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem.PortChannel.SubinterfacesItem, + adapter: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem, port_channel_subinterface_name: str, channel_group_id: int, ) -> dict: @@ -235,11 +232,11 @@ def _get_port_channel_subinterface_cfg( # Common port_channel_interface settings port_channel_interface = { "name": port_channel_subinterface_name, - "vlan_id": subinterface.get("vlan_id", subinterface["number"]), + "vlan_id": subinterface.vlan_id or subinterface.number, "encapsulation_vlan": { "client": { "encapsulation": "dot1q", - "vlan": get(subinterface, "encapsulation_vlan.client_dot1q", default=subinterface["number"]), + "vlan": subinterface.encapsulation_vlan.client_dot1q or subinterface.number, }, "network": { "encapsulation": "client", @@ -249,10 +246,10 @@ def _get_port_channel_subinterface_cfg( # EVPN A/A if ( - short_esi := self._get_short_esi(adapter, channel_group_id, short_esi=subinterface.get("short_esi"), hash_extra_value=str(subinterface["number"])) + short_esi := self._get_short_esi(adapter, channel_group_id, short_esi=subinterface.short_esi, hash_extra_value=str(subinterface.number)) ) is not None: port_channel_interface["evpn_ethernet_segment"] = { - "identifier": f"{self.shared_utils.evpn_short_esi_prefix}{short_esi}", + "identifier": f"{self.inputs.evpn_short_esi_prefix}{short_esi}", "route_target": short_esi_to_route_target(short_esi), } 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 06aaa2487de..45251b79108 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 @@ -8,10 +8,12 @@ from hashlib import sha256 from typing import TYPE_CHECKING -from pyavd._errors import AristaAvdError -from pyavd._utils import get, get_item, short_esi_to_route_target +from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError +from pyavd._utils import default, get_v2, short_esi_to_route_target if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + from . import AvdStructuredConfigConnectedEndpoints @@ -23,34 +25,32 @@ class UtilsMixin: """ @cached_property - def _filtered_connected_endpoints(self: AvdStructuredConfigConnectedEndpoints) -> list: + def _filtered_connected_endpoints( + self: AvdStructuredConfigConnectedEndpoints, + ) -> list[EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem]: """ Return list of endpoints defined under one of the keys in "connected_endpoints_keys" which are connected to this switch. Adapters are filtered to contain only the ones connected to this switch. """ filtered_connected_endpoints = [] - for connected_endpoints_key in self.shared_utils.connected_endpoints_keys: - connected_endpoints = get(self._hostvars, connected_endpoints_key["key"], default=[]) - for connected_endpoint in connected_endpoints: - if "adapters" not in connected_endpoint: - continue - + for connected_endpoints_key in self.inputs._dynamic_keys.connected_endpoints: + for connected_endpoint in connected_endpoints_key.value: filtered_adapters = [] - for adapter_index, adapter in enumerate(connected_endpoint["adapters"]): - adapter["context"] = f"{connected_endpoints_key['key']}[name={connected_endpoint['name']}].adapters[{adapter_index}]" + for adapter_index, adapter in enumerate(connected_endpoint.adapters): + adapter._context = f"{connected_endpoints_key.key}[name={connected_endpoint.name}].adapters[{adapter_index}]" adapter_settings = self.shared_utils.get_merged_adapter_settings(adapter) - - if self.shared_utils.hostname not in adapter_settings.get("switches", []): + if not adapter_settings.switches or self.shared_utils.hostname not in adapter_settings.switches: continue # Verify that length of all lists are the same - nodes_length = len(adapter_settings["switches"]) - endpoint_ports = adapter_settings.get("endpoint_ports") - if len(adapter_settings["switch_ports"]) != nodes_length or (endpoint_ports is not None and len(endpoint_ports) != nodes_length): + nodes_length = len(adapter_settings.switches) + endpoint_ports = adapter_settings.endpoint_ports + if len(adapter_settings.switch_ports) != nodes_length or (endpoint_ports and len(endpoint_ports) != nodes_length): msg = ( - f"Length of lists 'switches', 'switch_ports', 'endpoint_ports' (if used) did not match on adapter {adapter_index} on" - f" connected_endpoint '{connected_endpoint['name']}' under '{connected_endpoints_key['key']}'." + f"Length of lists 'switches' ({len(adapter.switches)}), 'switch_ports' ({len(adapter.switch_ports)}), " + f"'endpoint_ports' ({len(endpoint_ports) or '-'}) (if used) did not match on adapter {adapter_index} on" + f" connected_endpoint '{connected_endpoint.name}' under '{connected_endpoints_key.key}'." " Notice that some or all of these variables could be inherited from 'port_profiles'" ) raise AristaAvdError(msg) @@ -58,24 +58,21 @@ def _filtered_connected_endpoints(self: AvdStructuredConfigConnectedEndpoints) - filtered_adapters.append(adapter_settings) if filtered_adapters: - filtered_connected_endpoints.append( - { - **connected_endpoint, - "adapters": filtered_adapters, - "type": connected_endpoints_key["type"], - }, - ) + # The object was deepcopied inside "get_merged_adapter_settings" so we can modify it here. + connected_endpoint.adapters = filtered_adapters + connected_endpoint._type = self.inputs.connected_endpoints_keys[connected_endpoints_key.key].type + filtered_connected_endpoints.append(connected_endpoint) return filtered_connected_endpoints @cached_property - def _filtered_network_ports(self: AvdStructuredConfigConnectedEndpoints) -> list: + def _filtered_network_ports(self: AvdStructuredConfigConnectedEndpoints) -> list[EosDesigns.NetworkPortsItem]: """Return list of endpoints defined under "network_ports" which are connected to this switch.""" filtered_network_ports = [] - for index, network_port in enumerate(get(self._hostvars, "network_ports", default=[])): - network_port["context"] = f"network_ports[{index}]" + for index, network_port in enumerate(self.inputs.network_ports): + network_port._context = f"network_ports[{index}]" network_port_settings = self.shared_utils.get_merged_adapter_settings(network_port) - if not self._match_regexes(network_port_settings.get("switches"), self.shared_utils.hostname): + if not self._match_regexes(network_port_settings.switches, self.shared_utils.hostname): continue filtered_network_ports.append(network_port_settings) @@ -92,26 +89,26 @@ def _match_regexes(self: AvdStructuredConfigConnectedEndpoints, regexes: list, v def _get_short_esi( self: AvdStructuredConfigConnectedEndpoints, - adapter: dict, + adapter: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem, channel_group_id: int, short_esi: str | None = None, hash_extra_value: str = "", ) -> str | None: """Return short_esi for one adapter.""" - if len(set(adapter["switches"])) < 2 or not self.shared_utils.overlay_evpn or not self.shared_utils.overlay_vtep: + if len(set(adapter.switches)) < 2 or not self.shared_utils.overlay_evpn or not self.shared_utils.overlay_vtep: # Only configure ESI for multi-homing. return None # short_esi is only set when called from sub-interface port-channels. - if (short_esi is None) and (short_esi := get(adapter, "ethernet_segment.short_esi")) is None: + if (short_esi is None) and (short_esi := adapter.ethernet_segment.short_esi) is None: return None - endpoint_ports: list = adapter.get("endpoint_ports") + endpoint_ports: list = getattr(adapter, "endpoint_ports", []) short_esi = str(short_esi) if short_esi.lower() == "auto": esi_hash = sha256( "".join( - [hash_extra_value] + adapter["switches"][:2] + adapter["switch_ports"][:2] + endpoint_ports[:2] + [str(channel_group_id)], + [hash_extra_value] + adapter.switches[:2] + adapter.switch_ports[:2] + endpoint_ports[:2] + [str(channel_group_id)], ).encode("UTF-8"), ).hexdigest() short_esi = re.sub(r"([0-9a-f]{4})", "\\1:", esi_hash)[:14] @@ -122,28 +119,37 @@ def _get_short_esi( return short_esi - def _get_adapter_trunk_groups(self: AvdStructuredConfigConnectedEndpoints, adapter: dict, connected_endpoint: dict) -> dict | None: + def _get_adapter_trunk_groups( + self: AvdStructuredConfigConnectedEndpoints, + adapter: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem, + connected_endpoint: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem, + ) -> list | None: """Return trunk_groups for one adapter.""" - if self.shared_utils.enable_trunk_groups and "trunk" in adapter.get("mode", ""): - return get( - adapter, "trunk_groups", required=True, custom_error_msg=f"'trunk_groups' for the connected_endpoint {connected_endpoint['name']} is required." - ) + if not self.inputs.enable_trunk_groups or adapter.mode not in ["trunk", "trunk phone"]: + return None - return None + if adapter._get("trunk_groups") is None: + msg = f"'trunk_groups' for the connected_endpoint {connected_endpoint.name} is required." + raise AristaAvdInvalidInputsError(msg) + + return adapter.trunk_groups._as_list() - def _get_adapter_storm_control(self: AvdStructuredConfigConnectedEndpoints, adapter: dict) -> dict | None: + def _get_adapter_storm_control( + self: AvdStructuredConfigConnectedEndpoints, + adapter: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem, + ) -> dict | None: """Return storm_control for one adapter.""" - if self.shared_utils.platform_settings_feature_support_interface_storm_control: - return get(adapter, "storm_control") + if self.shared_utils.platform_settings.feature_support.interface_storm_control: + return adapter.storm_control._as_dict() return None def _get_adapter_evpn_ethernet_segment_cfg( self: AvdStructuredConfigConnectedEndpoints, - adapter: dict, - short_esi: str, + adapter: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem, + short_esi: str | None, node_index: int, - connected_endpoint: dict, + connected_endpoint: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem, default_df_algo: str | None = None, default_redundancy: str | None = None, ) -> dict | None: @@ -151,113 +157,124 @@ def _get_adapter_evpn_ethernet_segment_cfg( if short_esi is None: return None - adapter_ethernet_segment: dict = adapter.get("ethernet_segment", {}) evpn_ethernet_segment = { - "identifier": f"{self.shared_utils.evpn_short_esi_prefix}{short_esi}", - "redundancy": adapter_ethernet_segment.get("redundancy", default_redundancy), + "identifier": f"{self.inputs.evpn_short_esi_prefix}{short_esi}", + "redundancy": adapter.ethernet_segment.redundancy or default_redundancy, "route_target": short_esi_to_route_target(short_esi), } - if (designated_forwarder_algorithm := adapter_ethernet_segment.get("designated_forwarder_algorithm", default_df_algo)) is None: + if (designated_forwarder_algorithm := adapter.ethernet_segment.designated_forwarder_algorithm or default_df_algo) is None: return evpn_ethernet_segment if designated_forwarder_algorithm == "modulus": evpn_ethernet_segment["designated_forwarder_election"] = {"algorithm": "modulus"} elif designated_forwarder_algorithm == "auto": - auto_preferences = range((len(adapter["switches"]) - 1) * 100, -1, -100) + auto_preferences = range((len(adapter.switches) - 1) * 100, -1, -100) evpn_ethernet_segment["designated_forwarder_election"] = { "algorithm": "preference", "preference_value": auto_preferences[node_index], - "dont_preempt": adapter_ethernet_segment.get("dont_preempt"), + "dont_preempt": adapter.ethernet_segment.dont_preempt, } elif designated_forwarder_algorithm == "preference": # TODO: Add check for length of designated_forwarder_preferences - designated_forwarder_preferences = get( - adapter_ethernet_segment, + designated_forwarder_preferences = get_v2( + adapter.ethernet_segment, "designated_forwarder_preferences", required=True, - custom_error_msg=f"ethernet_segment.designated_forwarder_preferences for the connected_endpoint {connected_endpoint['name']}.", + custom_error_msg=f"ethernet_segment.designated_forwarder_preferences for the connected_endpoint {connected_endpoint.name}.", ) evpn_ethernet_segment["designated_forwarder_election"] = { "algorithm": "preference", "preference_value": designated_forwarder_preferences[node_index], - "dont_preempt": adapter_ethernet_segment.get("dont_preempt"), + "dont_preempt": adapter.ethernet_segment.dont_preempt, } return evpn_ethernet_segment - def _get_adapter_link_tracking_groups(self: AvdStructuredConfigConnectedEndpoints, adapter: dict) -> list | None: + def _get_adapter_link_tracking_groups( + self: AvdStructuredConfigConnectedEndpoints, + adapter: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem, + ) -> list | None: """Return link_tracking_groups for one adapter.""" - if self.shared_utils.link_tracking_groups is None or get(adapter, "link_tracking.enabled") is not True: + if self.shared_utils.link_tracking_groups is None or not adapter.link_tracking.enabled: return None return [ { - "name": get(adapter, "link_tracking.name", default=self.shared_utils.link_tracking_groups[0]["name"]), + "name": adapter.link_tracking.name or self.shared_utils.link_tracking_groups[0]["name"], "direction": "downstream", }, ] - def _get_adapter_ptp(self: AvdStructuredConfigConnectedEndpoints, adapter: dict) -> dict | None: + def _get_adapter_ptp( + self: AvdStructuredConfigConnectedEndpoints, adapter: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem + ) -> dict | None: """Return ptp for one adapter.""" - if get(adapter, "ptp.enabled") is not True: + if not adapter.ptp.enabled: return None ptp_config = {} # Apply PTP profile config - if (ptp_profile_name := get(adapter, "ptp.profile", default=self.shared_utils.ptp_profile_name)) is not None: - msg = f"PTP Profile '{ptp_profile_name}' referenced under {adapter['context']} does not exist in `ptp_profiles`." - ptp_config.update(get_item(self.shared_utils.ptp_profiles, "profile", ptp_profile_name, required=True, custom_error_msg=msg)) + if (ptp_profile_name := adapter.ptp.profile or self.shared_utils.ptp_profile_name) is not None: + if ptp_profile_name not in self.inputs.ptp_profiles: + msg = f"PTP Profile '{ptp_profile_name}' referenced under {adapter._context} does not exist in `ptp_profiles`." + raise AristaAvdInvalidInputsError(msg) + + ptp_config.update(self.inputs.ptp_profiles[ptp_profile_name]._as_dict(include_default_values=True)) ptp_config["enable"] = True - if get(adapter, "ptp.endpoint_role") != "bmca": + if adapter.ptp.endpoint_role != "bmca": ptp_config["role"] = "master" ptp_config.pop("profile", None) return ptp_config - def _get_adapter_poe(self: AvdStructuredConfigConnectedEndpoints, adapter: dict) -> dict | None: + def _get_adapter_poe( + self: AvdStructuredConfigConnectedEndpoints, + adapter: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem, + ) -> dict | None: """Return poe settings for one adapter.""" - if self.shared_utils.platform_settings_feature_support_poe: - return get(adapter, "poe") + if self.shared_utils.platform_settings.feature_support.poe: + return adapter.poe._as_dict() or None return None - def _get_adapter_phone(self: AvdStructuredConfigConnectedEndpoints, adapter: dict, connected_endpoint: dict) -> dict | None: + def _get_adapter_phone( + self: AvdStructuredConfigConnectedEndpoints, + adapter: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem, + connected_endpoint: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem, + ) -> dict | None: """Return phone settings for one adapter.""" - if (adapter_phone_vlan := get(adapter, "phone_vlan")) is None: + if not adapter.phone_vlan: return None # Verify that "mode" is set to "trunk phone" - if get(adapter, "mode") != "trunk phone": - msg = f"Setting 'phone_vlan' requires 'mode: trunk phone' to be set on connected endpoint '{connected_endpoint['name']}'." + if adapter.mode != "trunk phone": + msg = f"Setting 'phone_vlan' requires 'mode: trunk phone' to be set on connected endpoint '{connected_endpoint.name}'." raise AristaAvdError(msg) # Verify that "vlans" is not set, since data vlan is picked up from 'native_vlan'. - if get(adapter, "vlans") is not None: + if adapter.vlans: msg = ( "With 'phone_vlan' and 'mode: trunk phone' the data VLAN is set via 'native_vlan' instead of 'vlans'. Found 'vlans' on connected endpoint" - f" '{connected_endpoint['name']}'." - ) - raise AristaAvdError( - msg, + f" '{connected_endpoint.name}'." ) + raise AristaAvdError(msg) return { - "vlan": adapter_phone_vlan, - "trunk": get(adapter, "phone_trunk_mode"), + "vlan": adapter.phone_vlan, + "trunk": adapter.phone_trunk_mode, } - def _get_adapter_sflow(self: AvdStructuredConfigConnectedEndpoints, adapter: dict) -> dict | None: - if (adapter_sflow := get(adapter, "sflow", default=self.shared_utils.fabric_sflow_endpoints)) is not None: + def _get_adapter_sflow( + self: AvdStructuredConfigConnectedEndpoints, + adapter: EosDesigns._DynamicKeys.DynamicConnectedEndpointsItem.ConnectedEndpointsItem.AdaptersItem, + ) -> dict | None: + if (adapter_sflow := default(adapter.sflow, self.inputs.fabric_sflow.endpoints)) is not None: return {"enable": adapter_sflow} return None - - def _get_adapter_flow_tracking(self: AvdStructuredConfigConnectedEndpoints, adapter: dict) -> dict | None: - # Adapter flow tracking variables will be validated in _filtered_connected_endpoints - return self.shared_utils.get_flow_tracker(adapter, "endpoints") diff --git a/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/__init__.py b/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/__init__.py index ba4f82211bd..c8eced81158 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/__init__.py +++ b/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/__init__.py @@ -1,6 +1,10 @@ # Copyright (c) 2023-2024 Arista Networks, Inc. # Use of this source code is governed by the Apache License 2.0 # that can be found in the LICENSE file. +from __future__ import annotations + +from typing import TYPE_CHECKING + from pyavd._eos_designs.avdfacts import AvdFacts from .ethernet_interfaces import EthernetInterfacesMixin @@ -8,6 +12,9 @@ from .router_bgp import RouterBgpMixin from .router_ospf import RouterOspfMixin +if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + DATA_MODELS = ["core_interfaces", "l3_edge"] @@ -31,12 +38,15 @@ class AvdStructuredConfigCoreInterfacesAndL3Edge( The order of the @cached_properties methods imported from Mixins will also control the order in the output. """ + inputs_data: EosDesigns.CoreInterfaces | EosDesigns.L3Edge + def render(self) -> dict: """Render structured configs for core_interfaces and l3_Edge.""" result_list = [] for data_model in DATA_MODELS: self.data_model = data_model + self.inputs_data = self.inputs.core_interfaces if data_model == "core_interfaces" else self.inputs.l3_edge result_list.append(super().render()) self.clear_cache() diff --git a/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/ethernet_interfaces.py b/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/ethernet_interfaces.py index cc6e3bb6fd4..bf14a96483b 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/ethernet_interfaces.py +++ b/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/ethernet_interfaces.py @@ -6,7 +6,7 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import append_if_not_duplicate, get +from pyavd._utils import append_if_not_duplicate from pyavd.api.interface_descriptions import InterfaceDescriptionData from .utils import UtilsMixin @@ -27,11 +27,11 @@ def ethernet_interfaces(self: AvdStructuredConfigCoreInterfacesAndL3Edge) -> lis """Return structured config for ethernet_interfaces.""" ethernet_interfaces = [] - for p2p_link in self._filtered_p2p_links: - if p2p_link["data"]["port_channel_id"] is None: + for p2p_link, p2p_link_data in self._filtered_p2p_links: + if p2p_link_data["port_channel_id"] is None: # Ethernet interface - ethernet_interface = self._get_common_interface_cfg(p2p_link) - ethernet_interface["description"] = self._p2p_link_ethernet_description(p2p_link) + ethernet_interface = self._get_common_interface_cfg(p2p_link, p2p_link_data) + ethernet_interface["description"] = self._p2p_link_ethernet_description(p2p_link_data) ethernet_interface.update(self._get_ethernet_cfg(p2p_link)) # Remove None values @@ -46,9 +46,9 @@ def ethernet_interfaces(self: AvdStructuredConfigCoreInterfacesAndL3Edge) -> lis ) # Port-Channel members - for member in p2p_link["data"]["port_channel_members"]: - ethernet_interface = self._get_port_channel_member_cfg(p2p_link, member) - ethernet_interface["description"] = self._port_channel_member_description(p2p_link, member) + for member in p2p_link_data["port_channel_members"]: + ethernet_interface = self._get_port_channel_member_cfg(p2p_link, p2p_link_data, member) + ethernet_interface["description"] = self._port_channel_member_description(p2p_link_data, member) ethernet_interface.update(self._get_ethernet_cfg(p2p_link)) # Remove None values @@ -67,26 +67,26 @@ def ethernet_interfaces(self: AvdStructuredConfigCoreInterfacesAndL3Edge) -> lis return None - def _p2p_link_ethernet_description(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link: dict) -> str: + def _p2p_link_ethernet_description(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link_data: dict) -> str: return self.shared_utils.interface_descriptions.underlay_ethernet_interface( InterfaceDescriptionData( shared_utils=self.shared_utils, - description=get(p2p_link, "data.description"), - interface=p2p_link["data"]["interface"], + description=p2p_link_data.get("description"), + interface=p2p_link_data["interface"], link_type=self.data_model, - peer=p2p_link["data"]["peer"], - peer_interface=p2p_link["data"]["peer_interface"], + peer=p2p_link_data["peer"], + peer_interface=p2p_link_data["peer_interface"], ), ) - def _port_channel_member_description(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link: dict, member: dict) -> str: + def _port_channel_member_description(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link_data: dict, member: dict) -> str: return self.shared_utils.interface_descriptions.underlay_ethernet_interface( InterfaceDescriptionData( shared_utils=self.shared_utils, - description=get(p2p_link, "data.description"), + description=p2p_link_data.get("description"), interface=member["interface"], link_type=self.data_model, - peer=p2p_link["data"]["peer"], + peer=p2p_link_data["peer"], peer_interface=member["peer_interface"], ), ) diff --git a/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/port_channel_interfaces.py b/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/port_channel_interfaces.py index b69ca8a2f7e..5ceb3c5c3ae 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/port_channel_interfaces.py +++ b/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/port_channel_interfaces.py @@ -26,13 +26,13 @@ class PortChannelInterfacesMixin(UtilsMixin): def port_channel_interfaces(self: AvdStructuredConfigCoreInterfacesAndL3Edge) -> list | None: """Return structured config for port_channel_interfaces.""" port_channel_interfaces = [] - for p2p_link in self._filtered_p2p_links: - if p2p_link["data"]["port_channel_id"] is None: + for p2p_link, p2p_link_data in self._filtered_p2p_links: + if p2p_link_data["port_channel_id"] is None: continue # Port-Channel interface - port_channel_interface = self._get_common_interface_cfg(p2p_link) - port_channel_interface["description"] = self._p2p_link_port_channel_description(p2p_link) + port_channel_interface = self._get_common_interface_cfg(p2p_link, p2p_link_data) + port_channel_interface["description"] = self._p2p_link_port_channel_description(p2p_link_data) # Remove None values port_channel_interface = {key: value for key, value in port_channel_interface.items() if value is not None} @@ -44,16 +44,16 @@ def port_channel_interfaces(self: AvdStructuredConfigCoreInterfacesAndL3Edge) -> return None - def _p2p_link_port_channel_description(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link: dict) -> str: + def _p2p_link_port_channel_description(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link_data: dict) -> str: return self.shared_utils.interface_descriptions.underlay_port_channel_interface( InterfaceDescriptionData( shared_utils=self.shared_utils, - port_channel_description=default(get(p2p_link, "data.port_channel_description"), get(p2p_link, "data.description")), - interface=p2p_link["data"]["interface"], - port_channel_id=p2p_link["data"]["port_channel_id"], - peer_channel_group_id=p2p_link["data"]["peer_port_channel_id"], + port_channel_description=default(get(p2p_link_data, "port_channel_description"), get(p2p_link_data, "description")), + interface=p2p_link_data["interface"], + port_channel_id=p2p_link_data["port_channel_id"], + peer_channel_group_id=p2p_link_data["peer_port_channel_id"], link_type=self.data_model, - peer=p2p_link["data"]["peer"], - peer_interface=p2p_link["data"]["peer_interface"], + peer=p2p_link_data["peer"], + peer_interface=p2p_link_data["peer_interface"], ), ) diff --git a/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/router_bgp.py b/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/router_bgp.py index dfdd7b2b550..ff0211d6f8b 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/router_bgp.py +++ b/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/router_bgp.py @@ -30,39 +30,39 @@ def router_bgp(self: AvdStructuredConfigCoreInterfacesAndL3Edge) -> dict | None: neighbors = [] neighbor_interfaces = [] - for p2p_link in self._filtered_p2p_links: - if p2p_link.get("include_in_underlay_protocol", True) is not True: + for p2p_link, p2p_link_data in self._filtered_p2p_links: + if not p2p_link.include_in_underlay_protocol: continue - if p2p_link["data"]["bgp_as"] is None or p2p_link["data"]["peer_bgp_as"] is None: + if p2p_link_data["bgp_as"] is None or p2p_link_data["peer_bgp_as"] is None: msg = f"{self.data_model}.p2p_links.[].as or {self.data_model}.p2p_links_profiles.[].as" raise AristaAvdInvalidInputsError(msg) neighbor = { - "remote_as": p2p_link["data"]["peer_bgp_as"], - "peer": p2p_link["data"]["peer"], - "description": p2p_link["data"]["peer"], - "peer_group": self.shared_utils.bgp_peer_groups["ipv4_underlay_peers"]["name"], + "remote_as": p2p_link_data["peer_bgp_as"], + "peer": p2p_link_data["peer"], + "description": p2p_link_data["peer"], + "peer_group": self.inputs.bgp_peer_groups.ipv4_underlay_peers.name, } # RFC5549 - if self.shared_utils.underlay_rfc5549 and p2p_link.get("routing_protocol") != "ebgp": - neighbor_interfaces.append({"name": p2p_link["data"]["interface"], **neighbor}) + if self.inputs.underlay_rfc5549 and p2p_link.routing_protocol != "ebgp": + neighbor_interfaces.append({"name": p2p_link_data["interface"], **neighbor}) continue # Regular BGP Neighbors - if p2p_link["data"]["ip"] is None or p2p_link["data"]["peer_ip"] is None: + if p2p_link_data["ip"] is None or p2p_link_data["peer_ip"] is None: msg = f"{self.data_model}.p2p_links.[].ip, .subnet or .ip_pool" raise AristaAvdInvalidInputsError(msg) - neighbor["bfd"] = p2p_link.get("bfd") - if p2p_link["data"]["bgp_as"] != self.shared_utils.bgp_as: - neighbor["local_as"] = p2p_link["data"]["bgp_as"] + neighbor["bfd"] = p2p_link.bfd + if p2p_link_data["bgp_as"] != self.shared_utils.bgp_as: + neighbor["local_as"] = p2p_link_data["bgp_as"] # Remove None values neighbor = {key: value for key, value in neighbor.items() if value is not None} - neighbors.append({"ip_address": get_ip_from_ip_prefix(p2p_link["data"]["peer_ip"]), **neighbor}) + neighbors.append({"ip_address": get_ip_from_ip_prefix(p2p_link_data["peer_ip"]), **neighbor}) router_bgp = {} if neighbors: diff --git a/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/router_ospf.py b/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/router_ospf.py index d2db164ca24..8a1ed75c2ef 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/router_ospf.py +++ b/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/router_ospf.py @@ -25,14 +25,12 @@ def router_ospf(self: AvdStructuredConfigCoreInterfacesAndL3Edge) -> dict | None if not self.shared_utils.underlay_ospf: return None - no_passive_interfaces = [ - p2p_link["data"]["interface"] for p2p_link in self._filtered_p2p_links if p2p_link.get("include_in_underlay_protocol", True) is True - ] + no_passive_interfaces = [p2p_link_data["interface"] for p2p_link, p2p_link_data in self._filtered_p2p_links if p2p_link.include_in_underlay_protocol] if no_passive_interfaces: return { "process_ids": [ { - "id": self.shared_utils.underlay_ospf_process_id, + "id": self.inputs.underlay_ospf_process_id, "no_passive_interfaces": no_passive_interfaces, }, ], diff --git a/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/utils.py b/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/utils.py index f81576c0faf..74293364638 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/utils.py +++ b/python-avd/pyavd/_eos_designs/structured_config/core_interfaces_and_l3_edge/utils.py @@ -4,18 +4,21 @@ from __future__ import annotations import re -from copy import deepcopy from functools import cached_property from ipaddress import ip_network from itertools import islice -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, TypeVar -from pyavd._errors import AristaAvdInvalidInputsError -from pyavd._utils import default, get, get_item, merge +from pyavd._eos_designs.schema import EosDesigns +from pyavd._errors import AristaAvdInvalidInputsError, AristaAvdMissingVariableError +from pyavd._utils import default if TYPE_CHECKING: from . import AvdStructuredConfigCoreInterfacesAndL3Edge +T_P2pLinksItem = TypeVar("T_P2pLinksItem", EosDesigns.CoreInterfaces.P2pLinksItem, EosDesigns.L3Edge.P2pLinksItem) +T_P2pLinksProfiles = TypeVar("T_P2pLinksProfiles", EosDesigns.CoreInterfaces.P2pLinksProfiles, EosDesigns.L3Edge.P2pLinksProfiles) + class UtilsMixin: """ @@ -24,90 +27,72 @@ class UtilsMixin: Class should only be used as Mixin to a AvdStructuredConfig class. """ - @cached_property - def _p2p_links_profiles(self: AvdStructuredConfigCoreInterfacesAndL3Edge) -> list: - return get(self._hostvars, f"{self.data_model}.p2p_links_profiles", default=[]) - - @cached_property - def _p2p_links_ip_pools(self: AvdStructuredConfigCoreInterfacesAndL3Edge) -> list: - return get(self._hostvars, f"{self.data_model}.p2p_links_ip_pools", default=[]) - - @cached_property - def _p2p_links(self: AvdStructuredConfigCoreInterfacesAndL3Edge) -> list: - return get(self._hostvars, f"{self.data_model}.p2p_links", default=[]) - @cached_property def _p2p_links_sflow(self: AvdStructuredConfigCoreInterfacesAndL3Edge) -> bool | None: - return get(self._hostvars, f"fabric_sflow.{self.data_model}") + return self.inputs.fabric_sflow.core_interfaces if self.data_model == "core_interfaces" else self.inputs.fabric_sflow.l3_edge @cached_property - def _filtered_p2p_links(self: AvdStructuredConfigCoreInterfacesAndL3Edge) -> list: + def _filtered_p2p_links(self: AvdStructuredConfigCoreInterfacesAndL3Edge) -> list[tuple[T_P2pLinksItem, dict]]: """ Returns a filtered list of p2p_links, which only contains links with our hostname. For each links any referenced profiles are applied and IP addresses are resolved from pools or subnets. """ - if not (p2p_links := self._p2p_links): + if not (p2p_links := self.inputs_data.p2p_links): return [] # Apply p2p_profiles if set. Silently ignoring missing profile. - if self._p2p_links_profiles: - p2p_links = [self._apply_p2p_links_profile(p2p_link) for p2p_link in p2p_links] + p2p_links: list[T_P2pLinksItem] = [self._apply_p2p_links_profile(p2p_link) for p2p_link in p2p_links] # Filter to only include p2p_links with our hostname under "nodes" - p2p_links = [p2p_link for p2p_link in p2p_links if self.shared_utils.hostname in p2p_link.get("nodes", [])] + p2p_links = [p2p_link for p2p_link in p2p_links if self.shared_utils.hostname in p2p_link.nodes] if not p2p_links: return [] # Resolve IPs from subnet or p2p_pools. p2p_links = [self._resolve_p2p_ips(p2p_link) for p2p_link in p2p_links] - # Parse P2P data model and add simplified data - [p2p_link.update({"data": self._get_p2p_data(p2p_link)}) for p2p_link in p2p_links] - - return p2p_links + # Parse P2P data model and create simplified data + return [(p2p_link, self._get_p2p_data(p2p_link)) for p2p_link in p2p_links] - def _apply_p2p_links_profile(self: AvdStructuredConfigCoreInterfacesAndL3Edge, target_dict: dict) -> dict: - """Apply a profile to a p2p_link.""" - if "profile" not in target_dict: + def _apply_p2p_links_profile(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link: T_P2pLinksItem) -> T_P2pLinksItem: + """Apply a profile to a p2p_link. Always returns a new instance. TODO: Raise if profile is missing.""" + if not p2p_link.profile or p2p_link.profile not in self.inputs_data.p2p_links_profiles: # Nothing to do - return target_dict + return p2p_link._deepcopy() - profile = deepcopy(get_item(self._p2p_links_profiles, "name", target_dict["profile"], default={})) - merged_dict: dict = merge(profile, target_dict, list_merge="replace", destructive_merge=False) - merged_dict.pop("name", None) - return merged_dict + profile_as_p2p_link_item = self.inputs_data.p2p_links_profiles[p2p_link.profile]._cast_as(type(p2p_link), ignore_extra_keys=True) + return p2p_link._deepinherited(profile_as_p2p_link_item) - def _resolve_p2p_ips(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link: dict) -> dict: - if "ip" in p2p_link: + def _resolve_p2p_ips(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link: T_P2pLinksItem) -> T_P2pLinksItem: + if p2p_link.ip: # ip already set, so nothing to do return p2p_link - if "subnet" in p2p_link: + if p2p_link.subnet: # Resolve ip from subnet - subnet = ip_network(p2p_link["subnet"], strict=False) + subnet = ip_network(p2p_link.subnet, strict=False) - elif "ip_pool" not in p2p_link or "id" not in p2p_link or not self._p2p_links_ip_pools: + elif not p2p_link.ip_pool or not p2p_link.id or not self.inputs_data.p2p_links_ip_pools: # Subnet not set and not possible to resolve from pool. Returning original return p2p_link else: # Resolving subnet from pool - ip_pool = get_item(self._p2p_links_ip_pools, "name", p2p_link["ip_pool"], default={}) - ip_pool_subnet = ip_pool.get("ipv4_pool") - if not ip_pool_subnet: + if p2p_link.ip_pool not in self.inputs_data.p2p_links_ip_pools: return p2p_link - prefix_size = int(ip_pool.get("prefix_size", 31)) - link_id = int(p2p_link["id"]) - subnet = next(iter(islice(ip_network(ip_pool_subnet).subnets(new_prefix=prefix_size), link_id - 1, link_id))) + ip_pool = self.inputs_data.p2p_links_ip_pools[p2p_link.ip_pool] + if not ip_pool.ipv4_pool: + return p2p_link + subnet = next(iter(islice(ip_network(ip_pool.ipv4_pool).subnets(new_prefix=ip_pool.prefix_size), p2p_link.id - 1, p2p_link.id))) # hosts() return an iterator of all hosts in subnet. # islice() return a generator with only the first two iterations of hosts. # List comprehension runs through the generator creating string from each. - p2p_link["ip"] = [f"{ip}/{subnet.prefixlen}" for ip in islice(subnet.hosts(), 2)] + p2p_link.ip = [f"{ip}/{subnet.prefixlen}" for ip in islice(subnet.hosts(), 2)] return p2p_link - def _get_p2p_data(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link: dict) -> dict: + def _get_p2p_data(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link: T_P2pLinksItem) -> dict: """ Parses p2p_link data model and extracts information which is easier to parse. @@ -127,18 +112,18 @@ def _get_p2p_data(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link: di peer_bgp_as: } """ - index = p2p_link["nodes"].index(self.shared_utils.hostname) + index = p2p_link.nodes.index(self.shared_utils.hostname) peer_index = (index + 1) % 2 - peer = p2p_link["nodes"][peer_index] + peer = p2p_link.nodes[peer_index] peer_facts = self.shared_utils.get_peer_facts(peer, required=False) peer_type = "other" if peer_facts is None else peer_facts.get("type", "other") # Set ip or fallback to list with None values - ip = get(p2p_link, "ip", default=[None, None]) + ip = p2p_link.ip or [None, None] # Set bgp_as or fallback to list with None values - bgp_as = get(p2p_link, "as", default=[None, None]) + bgp_as = p2p_link.field_as or [None, None] # Set descriptions or fallback to list with None values - descriptions = get(p2p_link, "descriptions", default=[None, None]) + descriptions = p2p_link.descriptions or [None, None] data = { "peer": peer, @@ -150,23 +135,22 @@ def _get_p2p_data(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link: di "description": descriptions[index], } - node_child_interfaces = get(p2p_link, "port_channel.nodes_child_interfaces") - if (node_data := get_item(node_child_interfaces, "node", self.shared_utils.hostname)) is not None and ( - member_interfaces := node_data.get("interfaces") + if ( + self.shared_utils.hostname in p2p_link.port_channel.nodes_child_interfaces + and p2p_link.port_channel.nodes_child_interfaces[self.shared_utils.hostname].interfaces ): + node_data = p2p_link.port_channel.nodes_child_interfaces[self.shared_utils.hostname] # Port-channel - default_channel_id = int("".join(re.findall(r"\d", member_interfaces[0]))) - portchannel_id = node_data.get("channel_id", default_channel_id) - - peer = get_item( - node_child_interfaces, - "node", - peer, - var_name=f"{peer} under {self.data_model}.p2p_links.[].port_channel.nodes_child_interfaces", - ) - peer_member_interfaces = peer["interfaces"] - default_peer_channel_id = int("".join(re.findall(r"\d", peer_member_interfaces[0]))) - peer_id = peer.get("channel_id", default_peer_channel_id) + default_channel_id = int("".join(re.findall(r"\d", node_data.interfaces[0]))) + portchannel_id = node_data.channel_id or default_channel_id + + if peer not in p2p_link.port_channel.nodes_child_interfaces: + msg = f"{peer} under {self.data_model}.p2p_links.[].port_channel.nodes_child_interfaces" + raise AristaAvdMissingVariableError(msg) + + peer_data = p2p_link.port_channel.nodes_child_interfaces[peer] + default_peer_channel_id = int("".join(re.findall(r"\d", peer_data.interfaces[0]))) + peer_id = peer_data.channel_id or default_peer_channel_id data.update( { @@ -174,24 +158,24 @@ def _get_p2p_data(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link: di "peer_interface": f"Port-Channel{peer_id}", "port_channel_id": portchannel_id, "peer_port_channel_id": peer_id, - "port_channel_description": get(p2p_link, "port_channel.description"), + "port_channel_description": p2p_link.port_channel.description, "port_channel_members": [ { "interface": interface, - "peer_interface": peer_member_interfaces[index], + "peer_interface": peer_data.interfaces[index], } - for index, interface in enumerate(member_interfaces) + for index, interface in enumerate(node_data.interfaces) ], }, ) return data - if "interfaces" in p2p_link: + if p2p_link.interfaces: # Ethernet data.update( { - "interface": p2p_link["interfaces"][index], - "peer_interface": p2p_link["interfaces"][peer_index], + "interface": p2p_link.interfaces[index], + "peer_interface": p2p_link.interfaces[peer_index], "port_channel_id": None, "peer_port_channel_id": None, "port_channel_description": None, @@ -203,42 +187,42 @@ def _get_p2p_data(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link: di msg = f"{self.data_model}.p2p_links must have either 'interfaces' or 'port_channel' with correct members set." raise AristaAvdInvalidInputsError(msg) - def _get_common_interface_cfg(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link: dict) -> dict: + def _get_common_interface_cfg(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link: T_P2pLinksItem, p2p_link_data: dict) -> dict: """ Return partial structured_config for one p2p_link. Covers common config that is applicable to both port-channels and ethernet interfaces. This config will only be used on the main interface - so not port-channel members. """ - index = p2p_link["nodes"].index(self.shared_utils.hostname) + index = p2p_link.nodes.index(self.shared_utils.hostname) interface_cfg = { - "name": p2p_link["data"]["interface"], - "peer": p2p_link["data"]["peer"], - "peer_interface": p2p_link["data"]["peer_interface"], - "peer_type": p2p_link["data"]["peer_type"], + "name": p2p_link_data["interface"], + "peer": p2p_link_data["peer"], + "peer_interface": p2p_link_data["peer_interface"], + "peer_type": p2p_link_data["peer_type"], "switchport": {"enabled": False}, "shutdown": False, - "mtu": p2p_link.get("mtu", self.shared_utils.p2p_uplinks_mtu) if self.shared_utils.platform_settings_feature_support_per_interface_mtu else None, - "service_profile": p2p_link.get("qos_profile", self.shared_utils.p2p_uplinks_qos_profile), - "eos_cli": p2p_link.get("raw_eos_cli"), - "struct_cfg": get(p2p_link, "structured_config"), + "mtu": p2p_link._get("mtu", self.shared_utils.p2p_uplinks_mtu) if self.shared_utils.platform_settings.feature_support.per_interface_mtu else None, + "service_profile": p2p_link._get("qos_profile", self.inputs.p2p_uplinks_qos_profile), + "eos_cli": p2p_link.raw_eos_cli, + "struct_cfg": p2p_link.structured_config or None, } - if (ip := get(p2p_link, "ip")) is not None: - interface_cfg["ip_address"] = ip[index] + if p2p_link.ip: + interface_cfg["ip_address"] = p2p_link.ip[index] - if p2p_link.get("include_in_underlay_protocol", True) is True: - if p2p_link.get("underlay_multicast", False) and self.shared_utils.underlay_multicast is True: + if p2p_link.include_in_underlay_protocol: + if p2p_link.underlay_multicast and self.shared_utils.underlay_multicast: interface_cfg["pim"] = {"ipv4": {"sparse_mode": True}} - if (self.shared_utils.underlay_rfc5549 and p2p_link.get("routing_protocol") != "ebgp") or p2p_link.get("ipv6_enable") is True: + if (self.inputs.underlay_rfc5549 and p2p_link.routing_protocol != "ebgp") or p2p_link.ipv6_enable is True: interface_cfg["ipv6_enable"] = True if self.shared_utils.underlay_ospf: interface_cfg.update( { "ospf_network_point_to_point": True, - "ospf_area": self.shared_utils.underlay_ospf_area, + "ospf_area": self.inputs.underlay_ospf_area, }, ) @@ -246,21 +230,17 @@ def _get_common_interface_cfg(self: AvdStructuredConfigCoreInterfacesAndL3Edge, interface_cfg.update( { "isis_enable": self.shared_utils.isis_instance_name, - "isis_bfd": get(self._hostvars, "underlay_isis_bfd"), - "isis_metric": default(p2p_link.get("isis_metric"), self.shared_utils.isis_default_metric), - "isis_network_point_to_point": p2p_link.get("isis_network_type", "point-to-point") == "point-to-point", - "isis_hello_padding": p2p_link.get("isis_hello_padding", True), - "isis_circuit_type": default(p2p_link.get("isis_circuit_type"), self.shared_utils.isis_default_circuit_type), + "isis_bfd": self.inputs.underlay_isis_bfd or None, + "isis_metric": default(p2p_link.isis_metric, self.inputs.isis_default_metric), + "isis_network_point_to_point": p2p_link.isis_network_type == "point-to-point", + "isis_hello_padding": p2p_link.isis_hello_padding, + "isis_circuit_type": default(p2p_link.isis_circuit_type, self.inputs.isis_default_circuit_type), }, ) - if ( - isis_authentication_mode := default(p2p_link.get("isis_authentication_mode"), get(self._hostvars, "underlay_isis_authentication_mode")) - ) is not None: + if isis_authentication_mode := default(p2p_link.isis_authentication_mode, self.inputs.underlay_isis_authentication_mode): interface_cfg.setdefault("isis_authentication", {}).setdefault("both", {})["mode"] = isis_authentication_mode - if ( - isis_authentication_key := default(p2p_link.get("isis_authentication_key"), get(self._hostvars, "underlay_isis_authentication_key")) - ) is not None: + if (isis_authentication_key := default(p2p_link.isis_authentication_key, self.inputs.underlay_isis_authentication_key)) is not None: interface_cfg.setdefault("isis_authentication", {}).setdefault("both", {}).update( { "key": isis_authentication_key, @@ -268,48 +248,39 @@ def _get_common_interface_cfg(self: AvdStructuredConfigCoreInterfacesAndL3Edge, } ) - if p2p_link.get("macsec_profile"): - interface_cfg["mac_security"] = { - "profile": p2p_link["macsec_profile"], - } + if p2p_link.macsec_profile: + interface_cfg["mac_security"] = {"profile": p2p_link.macsec_profile} - if (p2p_link_sflow := get(p2p_link, "sflow", default=self._p2p_links_sflow)) is not None: + if (p2p_link_sflow := default(p2p_link.sflow, self._p2p_links_sflow)) is not None: interface_cfg["sflow"] = {"enable": p2p_link_sflow} - if (p2p_link_flow_tracking := self.shared_utils.get_flow_tracker(p2p_link, self.data_model)) is not None: + if (p2p_link_flow_tracking := self.shared_utils.get_flow_tracker(p2p_link.flow_tracking)) is not None: interface_cfg["flow_tracker"] = p2p_link_flow_tracking - if self.shared_utils.mpls_lsr and p2p_link.get("mpls_ip", True) is True: + if self.shared_utils.mpls_lsr and default(p2p_link.mpls_ip, True): # noqa: FBT003 interface_cfg["mpls"] = {"ip": True} - if p2p_link.get("include_in_underlay_protocol", True) is True and self.shared_utils.underlay_ldp and p2p_link.get("mpls_ldp", True) is True: - interface_cfg["mpls"].update( - { - "ldp": { - "interface": True, - "igp_sync": True, - }, - }, - ) + if p2p_link.include_in_underlay_protocol is True and self.shared_utils.underlay_ldp and default(p2p_link.mpls_ldp, True): # noqa: FBT003 + interface_cfg["mpls"]["ldp"] = {"interface": True, "igp_sync": True} return interface_cfg - def _get_ethernet_cfg(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link: dict) -> dict: + def _get_ethernet_cfg(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link: T_P2pLinksItem) -> dict: """ Return partial structured_config for one p2p_link. Covers config that is only applicable to ethernet interfaces. This config will only be used on both main interfaces and port-channel members. """ - ethernet_cfg = {"speed": p2p_link.get("speed")} + ethernet_cfg = {"speed": p2p_link.speed} - if get(p2p_link, "ptp.enabled") is not True: + if not p2p_link.ptp.enabled: return ethernet_cfg ptp_config = {} # Apply PTP profile config if self.shared_utils.ptp_enabled: - ptp_config.update(self.shared_utils.ptp_profile) + ptp_config.update(self.shared_utils.ptp_profile._as_dict(include_default_values=True)) ptp_config["enable"] = True ptp_config.pop("profile", None) @@ -317,7 +288,7 @@ def _get_ethernet_cfg(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link return ethernet_cfg - def _get_port_channel_member_cfg(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link: dict, member: dict) -> dict: + def _get_port_channel_member_cfg(self: AvdStructuredConfigCoreInterfacesAndL3Edge, p2p_link: T_P2pLinksItem, p2p_link_data: dict, member: dict) -> dict: """ Return partial structured_config for one p2p_link. @@ -325,12 +296,12 @@ def _get_port_channel_member_cfg(self: AvdStructuredConfigCoreInterfacesAndL3Edg """ return { "name": member["interface"], - "peer": p2p_link["data"]["peer"], + "peer": p2p_link_data["peer"], "peer_interface": member["peer_interface"], - "peer_type": p2p_link["data"]["peer_type"], + "peer_type": p2p_link_data["peer_type"], "shutdown": False, "channel_group": { - "id": p2p_link["data"]["port_channel_id"], - "mode": get(p2p_link, "port_channel.mode", default="active"), + "id": p2p_link_data["port_channel_id"], + "mode": p2p_link.port_channel.mode, }, } diff --git a/python-avd/pyavd/_eos_designs/structured_config/custom_structured_configuration/__init__.py b/python-avd/pyavd/_eos_designs/structured_config/custom_structured_configuration/__init__.py index cf67bd4c83c..6dc0d62b595 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/custom_structured_configuration/__init__.py +++ b/python-avd/pyavd/_eos_designs/structured_config/custom_structured_configuration/__init__.py @@ -20,15 +20,6 @@ class AvdStructuredConfigCustomStructuredConfiguration(AvdFacts): The Class uses AvdFacts, as the base class, to inherit _hostvars other attributes. """ - @cached_property - def _custom_structured_configuration_prefix(self) -> list: - """Reads custom_structured_configuration_prefix from hostvars and converts to list if necessary.""" - custom_structured_configuration_prefix = get(self._hostvars, "custom_structured_configuration_prefix", default=["custom_structured_configuration_"]) - if not isinstance(custom_structured_configuration_prefix, list): - return [custom_structured_configuration_prefix] - - return custom_structured_configuration_prefix - @cached_property def _router_bgp(self) -> dict | None: return get(self._hostvars, "router_bgp") @@ -48,7 +39,7 @@ def _extract_and_apply_struct_cfg_from_list_of_dicts(self, list_of_dicts: list, return struct_cfgs def _struct_cfg(self) -> list: - if (struct_cfg := get(self.shared_utils.switch_data_combined, "structured_config")) is not None: + if struct_cfg := self.shared_utils.node_config.structured_config._as_dict(strip_values=()): return [struct_cfg] return [] @@ -123,19 +114,8 @@ def _router_bgp_vlans(self) -> list: ] def _custom_structured_configurations(self) -> list[dict]: - if not self._custom_structured_configuration_prefix: - return [] - return [ - { - # Disable black to prevent whitespace before colon PEP8 E203 - # fmt: off - str(key)[len(prefix) :]: self._hostvars[key] - # fmt: on - for key in self._hostvars - if str(key).startswith(prefix) and key not in CUSTOM_STRUCTURED_CONFIGURATION_EXEMPT_KEYS - } - for prefix in self._custom_structured_configuration_prefix + custom_structured_configuration.value._as_dict(strip_values=()) for custom_structured_configuration in self.inputs._custom_structured_configurations ] def render(self) -> list[dict]: diff --git a/python-avd/pyavd/_eos_designs/structured_config/flows/__init__.py b/python-avd/pyavd/_eos_designs/structured_config/flows/__init__.py index 973fb3f03ac..fe4ae14546c 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/flows/__init__.py +++ b/python-avd/pyavd/_eos_designs/structured_config/flows/__init__.py @@ -6,8 +6,9 @@ from functools import cached_property from pyavd._eos_designs.avdfacts import AvdFacts +from pyavd._eos_designs.schema import EosDesigns from pyavd._errors import AristaAvdInvalidInputsError -from pyavd._utils import get, get_item, strip_null_from_data +from pyavd._utils import get, strip_null_from_data from pyavd.j2filters import natural_sort @@ -35,36 +36,36 @@ def sflow(self) -> dict | None: if not self._enable_sflow: return None - destinations = get(self._hostvars, "sflow_settings.destinations") - if destinations is None: + if not (destinations := self.inputs.sflow_settings.destinations): msg = "`sflow_settings.destinations` is required to configure `sflow`." raise AristaAvdInvalidInputsError(msg) - sflow_settings_vrfs = get(self._hostvars, "sflow_settings.vrfs", default=[]) + sflow_settings_vrfs = self.inputs.sflow_settings.vrfs # At this point we have at least one interface with sFlow enabled # and at least one destination. - sflow = { - "run": True, - "sample": get(self._hostvars, "sflow_settings.sample.rate"), - } + sflow = {"run": True, "sample": self.inputs.sflow_settings.sample.rate} # Using a temporary dict for VRFs sflow_vrfs = {} for destination in natural_sort(destinations, "destination"): - vrf = get(destination, "vrf") + destination: EosDesigns.SflowSettings.DestinationsItem + vrf = destination.vrf if vrf is None: vrf = self.shared_utils.default_mgmt_protocol_vrf source_interface = self.shared_utils.default_mgmt_protocol_interface elif vrf == "use_mgmt_interface_vrf": - if (self.shared_utils.mgmt_ip is None) and (self.shared_utils.ipv6_mgmt_ip is None): + if (self.shared_utils.node_config.mgmt_ip is None) and (self.shared_utils.node_config.ipv6_mgmt_ip is None): msg = "Unable to configure sFlow source-interface with 'use_mgmt_interface_vrf' since 'mgmt_ip' or 'ipv6_mgmt_ip' are not set." raise AristaAvdInvalidInputsError(msg) - vrf = self.shared_utils.mgmt_interface_vrf - source_interface = get(get_item(sflow_settings_vrfs, "name", vrf, default={}), "source_interface", default=self.shared_utils.mgmt_interface) + vrf = self.inputs.mgmt_interface_vrf + if vrf in sflow_settings_vrfs and sflow_settings_vrfs[vrf].source_interface: + source_interface = sflow_settings_vrfs[vrf].source_interface + else: + source_interface = self.shared_utils.mgmt_interface elif vrf == "use_inband_mgmt_vrf": # Check for missing interface @@ -74,22 +75,23 @@ def sflow(self) -> dict | None: # self.shared_utils.inband_mgmt_vrf returns None for the default VRF, but here we need "default" to avoid duplicates. vrf = self.shared_utils.inband_mgmt_vrf or "default" - source_interface = get( - get_item(sflow_settings_vrfs, "name", vrf, default={}), - "source_interface", - default=self.shared_utils.inband_mgmt_interface, - ) - + if vrf in sflow_settings_vrfs and sflow_settings_vrfs[vrf].source_interface: + source_interface = sflow_settings_vrfs[vrf].source_interface + else: + source_interface = self.shared_utils.inband_mgmt_interface + + # Default is none, meaning we will not configure a source interface for this VRF. + elif vrf in sflow_settings_vrfs and sflow_settings_vrfs[vrf].source_interface: + source_interface = sflow_settings_vrfs[vrf].source_interface else: - # Default is none, meaning we will not configure a source interface for this VRF. - source_interface = get(get_item(sflow_settings_vrfs, "name", vrf, default={}), "source_interface") + source_interface = None if vrf in [None, "default"]: # Add destination without VRF field sflow.setdefault("destinations", []).append( { - "destination": destination.get("destination"), - "port": destination.get("port"), + "destination": destination.destination, + "port": destination.port, }, ) sflow["source_interface"] = source_interface @@ -98,8 +100,8 @@ def sflow(self) -> dict | None: # Add destination with VRF field. sflow_vrfs.setdefault(vrf, {}).setdefault("destinations", []).append( { - "destination": destination.get("destination"), - "port": destination.get("port"), + "destination": destination.destination, + "port": destination.port, }, ) sflow_vrfs[vrf]["source_interface"] = source_interface @@ -123,39 +125,16 @@ def _enable_sflow(self) -> bool: return any(get(interface, "sflow.enable") is True for interface in get(self._hostvars, "port_channel_interfaces", default=[])) - @cached_property - def _default_flow_tracker(self) -> dict: - """ - Following configuration will be rendered based on the inputs. - - tracker FLOW-TRACKER - record export on inactive timeout 70000 - record export on interval 300000 - exporter ayush_exporter - collector 127.0.0.1 - local interface Loopback0 - template interval 3600000. - - Depending on the flow tracker type, some other default values like sample, no shutdown - will be added in further method - """ - return { - "name": self.shared_utils.default_flow_tracker_name, - "record_export": {"on_inactive_timeout": 70000, "on_interval": 300000}, - "exporters": [{"name": "CV-TELEMETRY", "collector": {"host": "127.0.0.1"}, "local_interface": "Loopback0", "template_interval": 3600000}], - } - - def resolve_flow_tracker_by_type(self, tracker_settings: dict) -> dict: + def resolve_flow_tracker_by_type(self, tracker_settings: EosDesigns.FlowTrackingSettings.TrackersItem) -> dict: tracker = { - "name": tracker_settings["name"], - "record_export": tracker_settings.get("record_export"), - "exporters": tracker_settings.get("exporters"), + "name": tracker_settings.name, + "record_export": tracker_settings.record_export._as_dict(), + "exporters": tracker_settings.exporters._as_list(), } if self.shared_utils.flow_tracking_type == "sampled": - sampled_settings = get(tracker_settings, "sampled", {}) - if (table_size := sampled_settings.get("table_size")) is not None: + if (table_size := tracker_settings.sampled.table_size) is not None: tracker["table_size"] = table_size - if (mpls := get(sampled_settings, "record_export.mpls")) is not None: + if (mpls := tracker_settings.sampled.record_export.mpls) is not None: tracker["record_export"]["mpls"] = mpls return tracker @@ -170,13 +149,12 @@ def flow_tracking(self) -> dict | None: flow_tracking = {} tracker_type = self.shared_utils.flow_tracking_type - flow_tracking_settings = get(self._hostvars, "flow_tracking_settings", default={}) - global_settings = get(flow_tracking_settings, tracker_type, default={}) - flow_tracking[tracker_type] = global_settings.copy() + global_settings = self.inputs.flow_tracking_settings.hardware if tracker_type == "hardware" else self.inputs.flow_tracking_settings.sampled + flow_tracking[tracker_type] = global_settings._as_dict() if tracker_type == "sampled": - flow_tracking[tracker_type]["sample"] = get(flow_tracking[tracker_type], "sample", 10000) - - all_trackers = get(flow_tracking_settings, "trackers", default=[]) + # asdict does not contain default values so we need to insert the default sample. + # TODO: consider if asdict should include defaults. + flow_tracking[tracker_type]["sample"] = global_settings.sample filtered_trackers = [] for tracker_name in configured_trackers: @@ -184,16 +162,15 @@ def flow_tracking(self) -> dict | None: We allow overriding the default flow tracker name, so if user has configured a tracker with the default tracker name, then we just use that, if not, we create a default config """ - default_tracker = tracker_name == self.shared_utils.default_flow_tracker_name - tracker = get_item( - all_trackers, - "name", - tracker_name, - required=not default_tracker, - custom_error_msg=f"{tracker_name} is being used for one of the interfaces, but is not configured in flow_tracking_settings", - ) - if default_tracker and tracker is None: - tracker = self._default_flow_tracker + default_tracker = next(iter(EosDesigns.FlowTrackingSettings().trackers)) + if tracker_name not in self.inputs.flow_tracking_settings.trackers: + if tracker_name == default_tracker.name: + tracker = default_tracker + else: + msg = f"{tracker_name} is being used for one of the interfaces, but is not configured in flow_tracking_settings" + raise AristaAvdInvalidInputsError(msg) + else: + tracker = self.inputs.flow_tracking_settings.trackers[tracker_name] filtered_trackers.append(self.resolve_flow_tracker_by_type(tracker)) @@ -202,7 +179,7 @@ def flow_tracking(self) -> dict | None: return flow_tracking - def _get_enabled_flow_trackers(self) -> bool: + def _get_enabled_flow_trackers(self) -> dict: """ Enable flow-tracking if any interface is enabled for flow-tracking. diff --git a/python-avd/pyavd/_eos_designs/structured_config/inband_management/__init__.py b/python-avd/pyavd/_eos_designs/structured_config/inband_management/__init__.py index 1bbd5dfb43c..f85160442c3 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/inband_management/__init__.py +++ b/python-avd/pyavd/_eos_designs/structured_config/inband_management/__init__.py @@ -21,11 +21,11 @@ def vlans(self) -> list | None: vlan_cfg = { "tenant": "system", - "name": self.shared_utils.inband_mgmt_vlan_name, + "name": self.shared_utils.node_config.inband_mgmt_vlan_name, } if self.shared_utils.configure_inband_mgmt or self.shared_utils.configure_inband_mgmt_ipv6: - return [{"id": self.shared_utils.inband_mgmt_vlan, **vlan_cfg}] + return [{"id": self.shared_utils.node_config.inband_mgmt_vlan, **vlan_cfg}] return [{"id": svi, **vlan_cfg} for svi in self.shared_utils.inband_management_parent_vlans] @@ -103,10 +103,10 @@ def ip_virtual_router_mac_address(self) -> str | None: if not self.shared_utils.inband_management_parent_vlans: return None - if self.shared_utils.virtual_router_mac_address is None: + if self.shared_utils.node_config.virtual_router_mac_address is None: msg = "'virtual_router_mac_address' must be set for inband management parent." raise AristaAvdInvalidInputsError(msg) - return str(self.shared_utils.virtual_router_mac_address).lower() + return str(self.shared_utils.node_config.virtual_router_mac_address).lower() @cached_property def router_bgp(self) -> dict | None: @@ -132,7 +132,7 @@ def prefix_lists(self) -> list | None: if not self.shared_utils.underlay_bgp: return None - if not self.shared_utils.underlay_filter_redistribute_connected: + if not self.inputs.underlay_filter_redistribute_connected: return None if self.shared_utils.overlay_routing_protocol == "none": @@ -166,7 +166,7 @@ def ipv6_prefix_lists(self) -> list | None: if not self.shared_utils.underlay_bgp: return None - if not self.shared_utils.underlay_filter_redistribute_connected: + if not self.inputs.underlay_filter_redistribute_connected: return None if not self._inband_mgmt_ipv6_parent: @@ -197,7 +197,7 @@ def route_maps(self) -> list | None: if not self.shared_utils.underlay_bgp: return None - if not self.shared_utils.underlay_filter_redistribute_connected: + if not self.inputs.underlay_filter_redistribute_connected: return None if self.shared_utils.overlay_routing_protocol == "none": @@ -217,7 +217,7 @@ def get_local_inband_mgmt_interface_cfg(self) -> dict: return strip_empties_from_dict( { "name": self.shared_utils.inband_mgmt_interface, - "description": self.shared_utils.inband_mgmt_description, + "description": self.shared_utils.node_config.inband_mgmt_description, "shutdown": False, "mtu": self.shared_utils.inband_mgmt_mtu, "vrf": self.shared_utils.inband_mgmt_vrf, @@ -231,7 +231,7 @@ def get_local_inband_mgmt_interface_cfg(self) -> dict: def get_parent_svi_cfg(self, vlan: int, subnet: str | None, ipv6_subnet: str | None) -> dict: svidict = { "name": f"Vlan{vlan}", - "description": self.shared_utils.inband_mgmt_description, + "description": self.shared_utils.node_config.inband_mgmt_description, "shutdown": False, "mtu": self.shared_utils.inband_mgmt_mtu, "vrf": self.shared_utils.inband_mgmt_vrf, diff --git a/python-avd/pyavd/_eos_designs/structured_config/metadata/cv_pathfinder.py b/python-avd/pyavd/_eos_designs/structured_config/metadata/cv_pathfinder.py index 16fa4d6c95a..0689e268c78 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/metadata/cv_pathfinder.py +++ b/python-avd/pyavd/_eos_designs/structured_config/metadata/cv_pathfinder.py @@ -3,10 +3,9 @@ # that can be found in the LICENSE file. from __future__ import annotations -from functools import cached_property from typing import TYPE_CHECKING -from pyavd._errors import AristaAvdError +from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError from pyavd._utils import get, get_all, get_item, strip_empties_from_list if TYPE_CHECKING: @@ -32,15 +31,18 @@ def _cv_pathfinder(self: AvdStructuredConfigMetadata) -> dict | None: if not self.shared_utils.is_cv_pathfinder_router: return None + region_name = self.shared_utils.wan_region.name if self.shared_utils.wan_region is not None else None + site_name = self.shared_utils.wan_site.name if self.shared_utils.wan_site is not None else None + # Pathfinder if self.shared_utils.is_cv_pathfinder_server: return { "role": self.shared_utils.cv_pathfinder_role, "ssl_profile": self.shared_utils.wan_stun_dtls_profile_name, "vtep_ip": self.shared_utils.vtep_ip, - "region": get(self.shared_utils.wan_region or {}, "name"), - "site": get(self.shared_utils.wan_site or {}, "name"), - "address": get(self.shared_utils.wan_site or {}, "location"), + "region": region_name, + "site": site_name, + "address": self.shared_utils.wan_site.location if self.shared_utils.wan_site is not None else None, "interfaces": self._metadata_interfaces(), "pathgroups": self._metadata_pathgroups(), "regions": self._metadata_regions(), @@ -52,9 +54,9 @@ def _cv_pathfinder(self: AvdStructuredConfigMetadata) -> dict | None: "role": self.shared_utils.cv_pathfinder_role, "ssl_profile": self.shared_utils.wan_stun_dtls_profile_name, "vtep_ip": self.shared_utils.vtep_ip, - "region": self.shared_utils.wan_region["name"], + "region": region_name, "zone": self.shared_utils.wan_zone["name"], - "site": self.shared_utils.wan_site["name"], + "site": site_name, "interfaces": self._metadata_interfaces(), "pathfinders": self._metadata_pathfinder_vtep_ips(), } @@ -75,54 +77,47 @@ def _metadata_interfaces(self: AvdStructuredConfigMetadata) -> list: def _metadata_pathgroups(self: AvdStructuredConfigMetadata) -> list: return [ { - "name": pathgroup["name"], + "name": pathgroup.name, "carriers": [ { - "name": carrier["name"], + "name": carrier.name, } - for carrier in self.shared_utils.wan_carriers - if carrier["path_group"] == pathgroup["name"] + for carrier in self.inputs.wan_carriers + if carrier.path_group == pathgroup.name ], "imported_carriers": [ { - "name": carrier["name"], + "name": carrier.name, } - for carrier in self.shared_utils.wan_carriers - if carrier["path_group"] in [imported_pathgroup["remote"] for imported_pathgroup in pathgroup.get("import_path_groups", [])] + for carrier in self.inputs.wan_carriers + if carrier.path_group in [imported_pathgroup.remote for imported_pathgroup in pathgroup.import_path_groups] ], } - for pathgroup in self.shared_utils.wan_path_groups + for pathgroup in self.inputs.wan_path_groups ] def _metadata_regions(self: AvdStructuredConfigMetadata) -> list: - regions = get( - self._hostvars, - "cv_pathfinder_regions", - required=True, - custom_error_msg="'cv_pathfinder_regions' key must be set when 'wan_mode' is 'cv-pathfinder'.", - ) + if not self.inputs.cv_pathfinder_regions: + msg = "'cv_pathfinder_regions' key must be set when 'wan_mode' is 'cv-pathfinder'." + raise AristaAvdInvalidInputsError(msg) + + regions = self.inputs.cv_pathfinder_regions return [ { - "name": region["name"], - "id": region["id"], + "name": region.name, + "id": region.id, "zones": [ { # TODO: Once we give configurable zones this should be updated - "name": f"{region['name']}-ZONE", + "name": f"{region.name}-ZONE", "id": 1, "sites": [ { - "name": site["name"], - "id": site["id"], - "location": ( - { - "address": site.get("location"), - } - if site.get("location") - else None - ), + "name": site.name, + "id": site.id, + "location": ({"address": site.location} if site.location else None), } - for site in region["sites"] + for site in region.sites ], }, ], @@ -133,9 +128,9 @@ def _metadata_regions(self: AvdStructuredConfigMetadata) -> list: def _metadata_pathfinder_vtep_ips(self: AvdStructuredConfigMetadata) -> list: return [ { - "vtep_ip": wan_route_server["vtep_ip"], + "vtep_ip": wan_route_server.vtep_ip, } - for wan_route_server in self.shared_utils.filtered_wan_route_servers.values() + for wan_route_server in self.shared_utils.filtered_wan_route_servers ] def _metadata_vrfs(self: AvdStructuredConfigMetadata) -> list: @@ -154,7 +149,7 @@ def _metadata_vrfs(self: AvdStructuredConfigMetadata) -> list: if not any( path_group.get("priority", 1) == 1 for path_group in lb_policy["path_groups"] - if path_group["name"] != self.shared_utils.wan_ha_path_group_name + if path_group["name"] != self.inputs.wan_ha.lan_ha_path_group_name ): msg = ( "At least one path-group must be configured with preference '1' or 'preferred' for " @@ -162,9 +157,7 @@ def _metadata_vrfs(self: AvdStructuredConfigMetadata) -> list: "If this is an auto-generated policy, ensure that at least one default_preference " "for a non excluded path-group is set to 'preferred' (or unset as this is the default)." ) - raise AristaAvdError( - msg, - ) + raise AristaAvdError(msg) return strip_empties_from_list( [ @@ -204,17 +197,8 @@ def _metadata_vrfs(self: AvdStructuredConfigMetadata) -> list: ], ) - @cached_property - def _wan_virtual_topologies_vrfs(self: AvdStructuredConfigMetadata) -> list[dict]: - """ - Unfiltered list of VRFs found under wan_virtual_topologies. - - Used to find VNI for each VRF used in cv_pathfinder. - """ - return get(self._hostvars, "wan_virtual_topologies.vrfs", default=[]) - def _get_vni_for_vrf_name(self: AvdStructuredConfigMetadata, vrf_name: str) -> int: - if (vrf := get_item(self._wan_virtual_topologies_vrfs, "name", vrf_name)) is None or (wan_vni := vrf.get("wan_vni")) is None: + if vrf_name not in self.inputs.wan_virtual_topologies.vrfs or (wan_vni := self.inputs.wan_virtual_topologies.vrfs[vrf_name].wan_vni) is None: if vrf_name == "default": return 1 diff --git a/python-avd/pyavd/_eos_designs/structured_config/metadata/cv_tags.py b/python-avd/pyavd/_eos_designs/structured_config/metadata/cv_tags.py index d48b14937ed..14c2e9741a3 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/metadata/cv_tags.py +++ b/python-avd/pyavd/_eos_designs/structured_config/metadata/cv_tags.py @@ -3,11 +3,10 @@ # that can be found in the LICENSE file. from __future__ import annotations -from functools import cached_property from typing import TYPE_CHECKING, Any from pyavd._errors import AristaAvdError -from pyavd._utils import default, get, get_item, strip_empties_from_dict, strip_empties_from_list +from pyavd._utils import default, get, strip_empties_from_dict, strip_empties_from_list if TYPE_CHECKING: from . import AvdStructuredConfigMetadata @@ -45,13 +44,9 @@ class CvTagsMixin: Class should only be used as Mixin to a AvdStructuredConfig class. """ - @cached_property - def _generate_cv_tags(self: AvdStructuredConfigMetadata) -> dict: - return get(self._hostvars, "generate_cv_tags", default={}) - def _cv_tags(self: AvdStructuredConfigMetadata) -> dict | None: """Generate the data structure `metadata.cv_tags`.""" - if not self._generate_cv_tags and not self.shared_utils.is_cv_pathfinder_router: + if not self.inputs.generate_cv_tags and not self.shared_utils.is_cv_pathfinder_router: return None device_tags = self._get_topology_hints() @@ -70,17 +65,17 @@ def _tag_dict(name: str, value: Any) -> dict | None: def _get_topology_hints(self: AvdStructuredConfigMetadata) -> list: """Return list of topology_hint tags.""" - if get(self._generate_cv_tags, "topology_hints") is not True: + if not self.inputs.generate_cv_tags.topology_hints: return [] - default_type_hint = get(self.shared_utils.node_type_key_data, "cv_tags_topology_type") + default_type_hint = self.shared_utils.node_type_key_data.cv_tags_topology_type return strip_empties_from_list( [ - self._tag_dict("topology_hint_datacenter", self.shared_utils.dc_name), + self._tag_dict("topology_hint_datacenter", self.inputs.dc_name), self._tag_dict("topology_hint_fabric", self.shared_utils.fabric_name), - self._tag_dict("topology_hint_pod", self.shared_utils.pod_name), - self._tag_dict("topology_hint_type", get(self._hostvars, "cv_tags_topology_type", default=default_type_hint)), - self._tag_dict("topology_hint_rack", default(self.shared_utils.rack, self.shared_utils.group)), + self._tag_dict("topology_hint_pod", self.inputs.pod_name), + self._tag_dict("topology_hint_type", default(self.inputs.cv_tags_topology_type, default_type_hint)), + self._tag_dict("topology_hint_rack", default(self.shared_utils.node_config.rack, self.shared_utils.group)), ], ) @@ -99,9 +94,12 @@ def _get_cv_pathfinder_device_tags(self: AvdStructuredConfigMetadata) -> list: if not self.shared_utils.is_cv_pathfinder_router: return [] + region_name = self.shared_utils.wan_region.name if self.shared_utils.wan_region is not None else None + site_name = self.shared_utils.wan_site.name if self.shared_utils.wan_site is not None else None + device_tags = [ self._tag_dict("Role", self.shared_utils.cv_pathfinder_role), - self._tag_dict("Region", get(self.shared_utils.wan_region or {}, "name")), + self._tag_dict("Region", region_name), ] if self.shared_utils.is_cv_pathfinder_server: device_tags.append(self._tag_dict("PathfinderSet", self.shared_utils.group or "PATHFINDERS")) @@ -109,7 +107,7 @@ def _get_cv_pathfinder_device_tags(self: AvdStructuredConfigMetadata) -> list: device_tags.extend( [ self._tag_dict("Zone", self.shared_utils.wan_zone["name"]), - self._tag_dict("Site", self.shared_utils.wan_site["name"]), + self._tag_dict("Site", site_name), ], ) @@ -117,46 +115,42 @@ def _get_cv_pathfinder_device_tags(self: AvdStructuredConfigMetadata) -> list: def _get_device_tags(self: AvdStructuredConfigMetadata) -> list: """Return list of device_tags.""" - if not (tags_to_generate := get(self._generate_cv_tags, "device_tags")): + if not (tags_to_generate := self.inputs.generate_cv_tags.device_tags): return [] device_tags = [] for generate_tag in tags_to_generate: - if generate_tag["name"] in INVALID_CUSTOM_DEVICE_TAGS: + if generate_tag.name in INVALID_CUSTOM_DEVICE_TAGS: msg = ( - f"The CloudVision tag name 'generate_cv_tags.device_tags[name={generate_tag['name']}] is invalid. " + f"The CloudVision tag name 'generate_cv_tags.device_tags[name={generate_tag.name}] is invalid. " "System Tags cannot be overridden. Try using a different name for this tag." ) - raise AristaAvdError( - msg, - ) + raise AristaAvdError(msg) # Get value from either 'value' key, structured config based on the 'data_path' key or raise. - if get(generate_tag, "value") is not None: - value = generate_tag["value"] - elif get(generate_tag, "data_path") is not None: - value = get(self._hostvars, generate_tag["data_path"]) + if generate_tag.value is not None: + value = generate_tag.value + elif generate_tag.data_path is not None: + value = get(self._hostvars, generate_tag.data_path) if type(value) in [list, dict]: msg = ( - f"'generate_cv_tags.device_tags[name={generate_tag['name']}].data_path' ({generate_tag['data_path']}) " + f"'generate_cv_tags.device_tags[name={generate_tag.name}].data_path' ({generate_tag.data_path}) " f"points to a variable of type {type(value).__name__}. This is not supported for cloudvision tag data_paths." ) - raise AristaAvdError( - msg, - ) + raise AristaAvdError(msg) else: - msg = f"'generate_cv_tags.device_tags[name={generate_tag['name']}]' is missing either a static 'value' or a dynamic 'data_path'" + msg = f"'generate_cv_tags.device_tags[name={generate_tag.name}]' is missing either a static 'value' or a dynamic 'data_path'" raise AristaAvdError(msg) # Silently ignoring empty values since structured config may vary between devices. if value: - device_tags.append(self._tag_dict(generate_tag["name"], value)) + device_tags.append(self._tag_dict(generate_tag.name, value)) return device_tags def _get_interface_tags(self: AvdStructuredConfigMetadata) -> list: """Return list of interface_tags.""" - if not (tags_to_generate := get(self._generate_cv_tags, "interface_tags", default=[])) and not self.shared_utils.is_cv_pathfinder_router: + if not (tags_to_generate := self.inputs.generate_cv_tags.interface_tags) and not self.shared_utils.is_cv_pathfinder_router: return [] interface_tags = [] @@ -164,27 +158,23 @@ def _get_interface_tags(self: AvdStructuredConfigMetadata) -> list: tags = [] for generate_tag in tags_to_generate: # Get value from either 'value' key, structured config based on the 'data_path' key or raise. - if get(generate_tag, "value") is not None: - value = generate_tag["value"] - elif get(generate_tag, "data_path") is not None: - value = get(ethernet_interface, generate_tag["data_path"]) + if generate_tag.value is not None: + value = generate_tag.value + elif generate_tag.data_path is not None: + value = get(ethernet_interface, generate_tag.data_path) if type(value) in [list, dict]: msg = ( - f"'generate_cv_tags.interface_tags[name={generate_tag['name']}].data_path' ({generate_tag['data_path']}) " + f"'generate_cv_tags.interface_tags[name={generate_tag.name}].data_path' ({generate_tag.data_path}) " f"points to a variable of type {type(value).__name__}. This is not supported for cloudvision tag data_paths." ) - raise AristaAvdError( - msg, - ) + raise AristaAvdError(msg) else: - msg = f"'generate_cv_tags.interface_tags[name={generate_tag['name']}]' is missing either a static 'value' or a dynamic 'data_path'" - raise AristaAvdError( - msg, - ) + msg = f"'generate_cv_tags.interface_tags[name={generate_tag.name}]' is missing either a static 'value' or a dynamic 'data_path'" + raise AristaAvdError(msg) # Silently ignoring empty values since structured config may vary between devices. if value: - tags.append(self._tag_dict(generate_tag["name"], value)) + tags.append(self._tag_dict(generate_tag.name, value)) if self.shared_utils.is_cv_pathfinder_router: tags.extend(self._get_cv_pathfinder_interface_tags(ethernet_interface)) @@ -204,18 +194,14 @@ def _get_cv_pathfinder_interface_tags(self: AvdStructuredConfigMetadata, etherne {"name": "Circuit", } ]. """ - if ethernet_interface["name"] in self._wan_interface_names: - wan_interface = get_item(self.shared_utils.wan_interfaces, "name", ethernet_interface["name"], required=True) + if ethernet_interface["name"] in self.shared_utils.wan_interfaces: + wan_interface = self.shared_utils.wan_interfaces[ethernet_interface["name"]] return strip_empties_from_list( [ self._tag_dict("Type", "wan"), - self._tag_dict("Carrier", get(wan_interface, "wan_carrier")), - self._tag_dict("Circuit", get(wan_interface, "wan_circuit_id")), + self._tag_dict("Carrier", wan_interface.wan_carrier), + self._tag_dict("Circuit", wan_interface.wan_circuit_id), ], ) return [self._tag_dict("Type", "lan")] - - @cached_property - def _wan_interface_names(self: AvdStructuredConfigMetadata) -> list: - return [wan_interface["name"] for wan_interface in self.shared_utils.wan_interfaces] diff --git a/python-avd/pyavd/_eos_designs/structured_config/mlag/__init__.py b/python-avd/pyavd/_eos_designs/structured_config/mlag/__init__.py index 34e0cba7b66..90abdddb325 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/mlag/__init__.py +++ b/python-avd/pyavd/_eos_designs/structured_config/mlag/__init__.py @@ -6,7 +6,7 @@ from functools import cached_property from pyavd._eos_designs.avdfacts import AvdFacts -from pyavd._utils import AvdStringFormatter, default, get, strip_empties_from_dict +from pyavd._utils import AvdStringFormatter, default, strip_empties_from_dict from pyavd.api.interface_descriptions import InterfaceDescriptionData from pyavd.j2filters import list_compress @@ -18,17 +18,9 @@ def render(self) -> dict: return super().render() return {} - @cached_property - def _trunk_groups_mlag_name(self) -> str: - return get(self.shared_utils.trunk_groups, "mlag.name", required=True) - - @cached_property - def _trunk_groups_mlag_l3_name(self) -> str: - return get(self.shared_utils.trunk_groups, "mlag_l3.name", required=True) - @cached_property def spanning_tree(self) -> dict: - vlans = [self.shared_utils.mlag_peer_vlan] + vlans = [self.shared_utils.node_config.mlag_peer_vlan] if self.shared_utils.mlag_peer_l3_vlan is not None: vlans.append(self.shared_utils.mlag_peer_l3_vlan) @@ -43,20 +35,20 @@ def vlans(self) -> list: "id": self.shared_utils.mlag_peer_l3_vlan, "tenant": "system", "name": AvdStringFormatter().format( - self.shared_utils.mlag_peer_l3_vlan_name, mlag_peer=self.shared_utils.mlag_peer, mlag_peer_l3_vlan=self.shared_utils.mlag_peer_l3_vlan + self.inputs.mlag_peer_l3_vlan_name, mlag_peer=self.shared_utils.mlag_peer, mlag_peer_l3_vlan=self.shared_utils.mlag_peer_l3_vlan ), - "trunk_groups": [self._trunk_groups_mlag_l3_name], + "trunk_groups": [self.inputs.trunk_groups.mlag_l3.name], }, ) vlans.append( { - "id": self.shared_utils.mlag_peer_vlan, + "id": self.shared_utils.node_config.mlag_peer_vlan, "tenant": "system", "name": AvdStringFormatter().format( - self.shared_utils.mlag_peer_vlan_name, mlag_peer=self.shared_utils.mlag_peer, mlag_peer_vlan=self.shared_utils.mlag_peer_vlan + self.inputs.mlag_peer_vlan_name, mlag_peer=self.shared_utils.mlag_peer, mlag_peer_vlan=self.shared_utils.node_config.mlag_peer_vlan ), - "trunk_groups": [self._trunk_groups_mlag_name], + "trunk_groups": [self.inputs.trunk_groups.mlag.name], }, ) return vlans @@ -70,7 +62,7 @@ def vlan_interfaces(self) -> list | None: Can also combine L3 configuration on the main MLAG VLAN """ # Create Main MLAG VLAN Interface - main_vlan_interface_name = f"Vlan{self.shared_utils.mlag_peer_vlan}" + main_vlan_interface_name = f"Vlan{self.shared_utils.node_config.mlag_peer_vlan}" main_vlan_interface = { "name": main_vlan_interface_name, "description": self.shared_utils.interface_descriptions.mlag_peer_svi( @@ -78,26 +70,24 @@ def vlan_interfaces(self) -> list | None: ), "shutdown": False, "no_autostate": True, - "struct_cfg": self.shared_utils.mlag_peer_vlan_structured_config, + "struct_cfg": self.shared_utils.node_config.mlag_peer_vlan_structured_config._as_dict(strip_values=()) or None, "mtu": self.shared_utils.p2p_uplinks_mtu, } - if self.shared_utils.mlag_peer_address_family == "ipv6": - main_vlan_interface["ipv6_address"] = f"{self.shared_utils.mlag_ip}/{self.shared_utils.fabric_ip_addressing_mlag_ipv6_prefix_length}" + if self.shared_utils.node_config.mlag_peer_address_family == "ipv6": + main_vlan_interface["ipv6_address"] = f"{self.shared_utils.mlag_ip}/{self.inputs.fabric_ip_addressing.mlag.ipv6_prefix_length}" else: - main_vlan_interface["ip_address"] = f"{self.shared_utils.mlag_ip}/{self.shared_utils.fabric_ip_addressing_mlag_ipv4_prefix_length}" + main_vlan_interface["ip_address"] = f"{self.shared_utils.mlag_ip}/{self.inputs.fabric_ip_addressing.mlag.ipv4_prefix_length}" if not self.shared_utils.mlag_l3 or self.shared_utils.underlay_routing_protocol == "none": return [strip_empties_from_dict(main_vlan_interface)] # Create L3 data which will go on either a dedicated l3 vlan or the main mlag vlan - l3_cfg = { - "struct_cfg": get(self.shared_utils.switch_data_combined, "mlag_peer_l3_vlan_structured_config"), - } + l3_cfg = {"struct_cfg": self.shared_utils.node_config.mlag_peer_l3_vlan_structured_config._as_dict(strip_values=()) or None} if self.shared_utils.underlay_routing_protocol == "ospf": l3_cfg.update( { "ospf_network_point_to_point": True, - "ospf_area": self.shared_utils.underlay_ospf_area, + "ospf_area": self.inputs.underlay_ospf_area, }, ) @@ -105,33 +95,33 @@ def vlan_interfaces(self) -> list | None: l3_cfg.update( { "isis_enable": self.shared_utils.isis_instance_name, - "isis_bfd": get(self._hostvars, "underlay_isis_bfd"), + "isis_bfd": self.inputs.underlay_isis_bfd or None, "isis_metric": 50, "isis_network_point_to_point": True, } ) - if (isis_authentication_mode := get(self._hostvars, "underlay_isis_authentication_mode")) is not None: - l3_cfg.setdefault("isis_authentication", {}).setdefault("both", {})["mode"] = isis_authentication_mode + if self.inputs.underlay_isis_authentication_mode: + l3_cfg.setdefault("isis_authentication", {}).setdefault("both", {})["mode"] = self.inputs.underlay_isis_authentication_mode - if (isis_authentication_key := get(self._hostvars, "underlay_isis_authentication_key")) is not None: + if self.inputs.underlay_isis_authentication_key is not None: l3_cfg.setdefault("isis_authentication", {}).setdefault("both", {}).update( { - "key": isis_authentication_key, + "key": self.inputs.underlay_isis_authentication_key, "key_type": "7", } ) if self.shared_utils.underlay_multicast: l3_cfg["pim"] = {"ipv4": {"sparse_mode": True}} - if self.shared_utils.underlay_rfc5549: + if self.inputs.underlay_rfc5549: l3_cfg["ipv6_enable"] = True # Add L3 config if the main interface is also used for L3 peering if self.shared_utils.mlag_peer_l3_vlan is None: main_vlan_interface.update(l3_cfg) # Applying structured config again in the case it is set on both l3vlan and main vlan - if self.shared_utils.mlag_peer_vlan_structured_config is not None: - main_vlan_interface["struct_cfg"] = self.shared_utils.mlag_peer_vlan_structured_config + if self.shared_utils.node_config.mlag_peer_vlan_structured_config is not None: + main_vlan_interface["struct_cfg"] = self.shared_utils.node_config.mlag_peer_vlan_structured_config._as_dict(strip_values=()) return [strip_empties_from_dict(main_vlan_interface)] @@ -145,8 +135,8 @@ def vlan_interfaces(self) -> list | None: "shutdown": False, "mtu": self.shared_utils.p2p_uplinks_mtu, } - if not self.shared_utils.underlay_rfc5549: - l3_vlan_interface["ip_address"] = f"{self.shared_utils.mlag_l3_ip}/{self.shared_utils.fabric_ip_addressing_mlag_ipv4_prefix_length}" + if not self.inputs.underlay_rfc5549: + l3_vlan_interface["ip_address"] = f"{self.shared_utils.mlag_l3_ip}/{self.inputs.fabric_ip_addressing.mlag.ipv4_prefix_length}" l3_vlan_interface.update(l3_cfg) @@ -173,28 +163,28 @@ def port_channel_interfaces(self) -> list: "enabled": True, "mode": "trunk", "trunk": { - "groups": [self._trunk_groups_mlag_name], - "allowed_vlan": get(self.shared_utils.switch_data_combined, "mlag_peer_link_allowed_vlans"), + "groups": [self.inputs.trunk_groups.mlag.name], + "allowed_vlan": self.shared_utils.node_config.mlag_peer_link_allowed_vlans, }, }, "shutdown": False, - "service_profile": self.shared_utils.p2p_uplinks_qos_profile, - "struct_cfg": get(self.shared_utils.switch_data_combined, "mlag_port_channel_structured_config"), - "flow_tracker": self.shared_utils.get_flow_tracker(None, "mlag_interfaces"), + "service_profile": self.inputs.p2p_uplinks_qos_profile, + "struct_cfg": self.shared_utils.node_config.mlag_port_channel_structured_config._as_dict(strip_values=()) or None, + "flow_tracker": self.shared_utils.get_flow_tracker(self.inputs.fabric_flow_tracking.mlag_interfaces), } - if self.shared_utils.mlag_l3 is True and self._trunk_groups_mlag_l3_name != self._trunk_groups_mlag_name: + if self.shared_utils.mlag_l3 is True and self.inputs.trunk_groups.mlag_l3.name != self.inputs.trunk_groups.mlag.name: # Add mlag_l3 trunk group even if we reuse the MLAG trunk group for underlay peering # since this trunk group is also used for overlay iBGP peerings # except in the case where the same trunk group name is defined. - port_channel_interface["switchport"]["trunk"]["groups"].append(self._trunk_groups_mlag_l3_name) + port_channel_interface["switchport"]["trunk"]["groups"].append(self.inputs.trunk_groups.mlag_l3.name) - if (self.shared_utils.fabric_sflow_mlag_interfaces) is not None: - port_channel_interface["sflow"] = {"enable": self.shared_utils.fabric_sflow_mlag_interfaces} + if (self.inputs.fabric_sflow.mlag_interfaces) is not None: + port_channel_interface["sflow"] = {"enable": self.inputs.fabric_sflow.mlag_interfaces} - if self.shared_utils.ptp_enabled and self.shared_utils.ptp_mlag: + if self.shared_utils.ptp_enabled and self.shared_utils.node_config.ptp.mlag: ptp_config = {} - ptp_config.update(self.shared_utils.ptp_profile) + ptp_config.update(self.shared_utils.ptp_profile._as_dict(include_default_values=True)) ptp_config["enable"] = True ptp_config.pop("profile", None) # Apply ptp config to port-channel @@ -208,12 +198,9 @@ def port_channel_interfaces(self) -> list: @cached_property def ethernet_interfaces(self) -> list: - """Return dict with Ethernet Interfaces used for MLAG Peer Link.""" - if not (mlag_interfaces := self.shared_utils.mlag_interfaces): - return None - + """Return list of Ethernet Interfaces used for MLAG Peer Link.""" ethernet_interfaces = [] - for index, mlag_interface in enumerate(mlag_interfaces): + for index, mlag_interface in enumerate(self.shared_utils.mlag_interfaces): ethernet_interface = { "name": mlag_interface, "peer": self.shared_utils.mlag_peer, @@ -232,7 +219,7 @@ def ethernet_interfaces(self) -> list: "id": self.shared_utils.mlag_port_channel_id, "mode": "active", }, - "speed": self.shared_utils.mlag_interfaces_speed, + "speed": self.shared_utils.node_config.mlag_interfaces_speed, } if self.shared_utils.get_mlag_peer_fact("inband_ztp", required=False) is True: ethernet_interface.update( @@ -246,23 +233,19 @@ def ethernet_interfaces(self) -> list: def mlag_configuration(self) -> dict: """Return Structured Config for MLAG Configuration.""" mlag_configuration = { - "domain_id": get(self.shared_utils.switch_data_combined, "mlag_domain_id", default=self.shared_utils.group), - "local_interface": f"Vlan{self.shared_utils.mlag_peer_vlan}", + "domain_id": default(self.shared_utils.node_config.mlag_domain_id, self.shared_utils.group), + "local_interface": f"Vlan{self.shared_utils.node_config.mlag_peer_vlan}", "peer_address": self.shared_utils.mlag_peer_ip, "peer_link": f"Port-Channel{self.shared_utils.mlag_port_channel_id}", - "reload_delay_mlag": str(get(self.shared_utils.platform_settings, "reload_delay.mlag", default="")) or None, - "reload_delay_non_mlag": str(get(self.shared_utils.platform_settings, "reload_delay.non_mlag", default="")) or None, + "reload_delay_mlag": str(default(self.shared_utils.platform_settings.reload_delay.mlag, "")) or None, + "reload_delay_non_mlag": str(default(self.shared_utils.platform_settings.reload_delay.non_mlag, "")) or None, } - if ( - get(self.shared_utils.switch_data_combined, "mlag_dual_primary_detection", default=False) is True - and self.shared_utils.mlag_peer_mgmt_ip is not None - and (self.shared_utils.mgmt_interface_vrf) is not None - ): + if self.shared_utils.node_config.mlag_dual_primary_detection and self.shared_utils.mlag_peer_mgmt_ip and self.inputs.mgmt_interface_vrf: mlag_configuration.update( { "peer_address_heartbeat": { "peer_ip": self.shared_utils.mlag_peer_mgmt_ip, - "vrf": self.shared_utils.mgmt_interface_vrf, + "vrf": self.inputs.mgmt_interface_vrf, }, "dual_primary_detection_delay": 5, }, @@ -279,7 +262,7 @@ def route_maps(self) -> list[dict] | None: TODO: Partially duplicated in network_services. Should be moved to a common class """ - if not (self.shared_utils.mlag_l3 is True and self.shared_utils.mlag_ibgp_origin_incomplete is True and self.shared_utils.underlay_bgp): + if not (self.shared_utils.mlag_l3 and self.shared_utils.node_config.mlag_ibgp_origin_incomplete and self.shared_utils.underlay_bgp): return None return [ @@ -308,14 +291,14 @@ def router_bgp(self) -> dict | None: return None # MLAG Peer group - peer_group_name = self.shared_utils.bgp_peer_groups["mlag_ipv4_underlay_peer"]["name"] + peer_group_name = self.inputs.bgp_peer_groups.mlag_ipv4_underlay_peer.name router_bgp = self._router_bgp_mlag_peer_group() - vlan = default(self.shared_utils.mlag_peer_l3_vlan, self.shared_utils.mlag_peer_vlan) + vlan = default(self.shared_utils.mlag_peer_l3_vlan, self.shared_utils.node_config.mlag_peer_vlan) interface_name = f"Vlan{vlan}" # Underlay MLAG peering - if self.shared_utils.underlay_rfc5549: + if self.inputs.underlay_rfc5549: router_bgp["neighbor_interfaces"] = [ { "name": interface_name, @@ -323,7 +306,7 @@ def router_bgp(self) -> dict | None: "peer": self.shared_utils.mlag_peer, "remote_as": self.shared_utils.bgp_as, "description": AvdStringFormatter().format( - self.shared_utils.mlag_bgp_peer_description, + self.inputs.mlag_bgp_peer_description, mlag_peer=self.shared_utils.mlag_peer, interface=interface_name, peer_interface=interface_name, @@ -339,7 +322,7 @@ def router_bgp(self) -> dict | None: "peer_group": peer_group_name, "peer": self.shared_utils.mlag_peer, "description": AvdStringFormatter().format( - self.shared_utils.mlag_bgp_peer_description, + self.inputs.mlag_bgp_peer_description, mlag_peer=self.shared_utils.mlag_peer, interface=interface_name, peer_interface=interface_name, @@ -355,21 +338,21 @@ def _router_bgp_mlag_peer_group(self) -> dict: TODO: Duplicated in network_services. Should be moved to a common class """ - peer_group_name = self.shared_utils.bgp_peer_groups["mlag_ipv4_underlay_peer"]["name"] + peer_group_name = self.inputs.bgp_peer_groups.mlag_ipv4_underlay_peer.name router_bgp = {} peer_group = { "name": peer_group_name, "type": "ipv4", "remote_as": self.shared_utils.bgp_as, "next_hop_self": True, - "description": AvdStringFormatter().format(self.shared_utils.mlag_bgp_peer_group_description, mlag_peer=self.shared_utils.mlag_peer), - "password": self.shared_utils.bgp_peer_groups["mlag_ipv4_underlay_peer"]["password"], - "bfd": self.shared_utils.bgp_peer_groups["ipv4_underlay_peers"]["bfd"], + "description": AvdStringFormatter().format(self.inputs.mlag_bgp_peer_group_description, mlag_peer=self.shared_utils.mlag_peer), + "password": self.inputs.bgp_peer_groups.mlag_ipv4_underlay_peer.password, + "bfd": self.inputs.bgp_peer_groups.ipv4_underlay_peers.bfd or None, "maximum_routes": 12000, "send_community": "all", - "struct_cfg": self.shared_utils.bgp_peer_groups["mlag_ipv4_underlay_peer"]["structured_config"], + "struct_cfg": self.inputs.bgp_peer_groups.mlag_ipv4_underlay_peer.structured_config._as_dict(strip_values=()) or None, } - if self.shared_utils.mlag_ibgp_origin_incomplete is True: + if self.shared_utils.node_config.mlag_ibgp_origin_incomplete: peer_group["route_map_in"] = "RM-MLAG-PEER-IN" router_bgp["peer_groups"] = [strip_empties_from_dict(peer_group)] @@ -385,7 +368,7 @@ def _router_bgp_mlag_peer_group(self) -> dict: } address_family_ipv4_peer_group = {"name": peer_group_name, "activate": True} - if self.shared_utils.underlay_rfc5549: + if self.inputs.underlay_rfc5549: address_family_ipv4_peer_group["next_hop"] = {"address_family_ipv6": {"enabled": True, "originate": True}} router_bgp["address_family_ipv4"] = {"peer_groups": [address_family_ipv4_peer_group]} diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/application_traffic_recognition.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/application_traffic_recognition.py index 4b96cd7ebea..5dddeead19a 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/application_traffic_recognition.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/application_traffic_recognition.py @@ -3,9 +3,10 @@ # that can be found in the LICENSE file. from __future__ import annotations -from functools import cached_property +from functools import cached_property, partial from typing import TYPE_CHECKING +from pyavd._errors import AristaAvdInvalidInputsError from pyavd._utils import append_if_not_duplicate, get, get_item, strip_empties_from_dict from .utils import UtilsMixin @@ -116,7 +117,7 @@ def _generate_control_plane_application_profile(self: AvdStructuredConfigNetwork ipv4_prefixes_field_sets = get(app_dict, "field_sets.ipv4_prefixes", []) if get_item(ipv4_prefixes_field_sets, "name", self._wan_cp_app_dst_prefix) is not None: return - pathfinder_vtep_ips = [f"{wan_rs_data.get('vtep_ip')}/32" for wan_rs, wan_rs_data in self.shared_utils.filtered_wan_route_servers.items()] + pathfinder_vtep_ips = [f"{wan_rs.vtep_ip}/32" for wan_rs in self.shared_utils.filtered_wan_route_servers] app_dict.setdefault("field_sets", {}).setdefault("ipv4_prefixes", []).append( { "name": self._wan_cp_app_dst_prefix, @@ -142,108 +143,80 @@ def _filtered_application_classification(self: AvdStructuredConfigNetworkService For applications - the existence cannot be verified as there are 4000+ applications built-in in the DPI engine used by EOS. """ - input_application_classification = get(self._hostvars, "application_classification", {}) # Application profiles first application_profiles = [] - def _append_object_to_list_of_dicts(path: str, obj_name: str, list_of_dicts: list, message: str | None = None, *, required: bool = True) -> None: - """ - Helper function. - - Technically impossible to get a duplicate, just reusing the method when the same application is used in multiple places. - """ - if ( - obj := get_item( - get(input_application_classification, path, default=[]), - "name", - obj_name, - required=required, - custom_error_msg=message, - ) - ) is None: - return - - append_if_not_duplicate( - list_of_dicts=list_of_dicts, - primary_key="name", - new_dict=obj, - context="Application traffic recognition", - context_keys=["name"], - ) + append_dict_to_list_of_dicts = partial(append_if_not_duplicate, primary_key="name", context="Application traffic recognition", context_keys=["name"]) for policy in self._filtered_wan_policies: - if policy.get("is_default"): - _append_object_to_list_of_dicts( - path="application_profiles", - obj_name=self._wan_control_plane_application_profile_name, + if policy.get("is_default") and self._wan_control_plane_application_profile_name in self.inputs.application_classification.application_profiles: + append_dict_to_list_of_dicts( list_of_dicts=application_profiles, - required=False, + new_dict=self.inputs.application_classification.application_profiles[self._wan_control_plane_application_profile_name]._as_dict(), ) for match in get(policy, "matches", []): application_profile = get(match, "application_profile", required=True) - if application_profile == self._wan_control_plane_application_profile_name: - # Special handling for control plane as it could be injected later. - _append_object_to_list_of_dicts( - path="application_profiles", - obj_name=application_profile, - list_of_dicts=application_profiles, - required=False, - ) - else: - _append_object_to_list_of_dicts( - path="application_profiles", - obj_name=application_profile, - list_of_dicts=application_profiles, - message=( - f"The application profile {application_profile} used in policy {policy['name']} " - "is not defined in 'application_classification.application_profiles'." - ), + + if application_profile not in self.inputs.application_classification.application_profiles: + if application_profile == self._wan_control_plane_application_profile_name: + # Ignore for control plane as it could be injected later. + continue + + msg = ( + f"The application profile {application_profile} used in policy {policy['name']} " + "is not defined in 'application_classification.application_profiles'." ) + raise AristaAvdInvalidInputsError(msg) + + append_dict_to_list_of_dicts( + list_of_dicts=application_profiles, new_dict=self.inputs.application_classification.application_profiles[application_profile]._as_dict() + ) + if (default_match := policy.get("default_match")) is not None: application_profile = get(default_match, "application_profile", default="default") if application_profile != "default": - _append_object_to_list_of_dicts( - path="application_profiles", - obj_name=application_profile, - list_of_dicts=application_profiles, - message=( + if application_profile not in self.inputs.application_classification.application_profiles: + msg = ( f"The application profile {application_profile} used in policy {policy['name']} " "is not defined in 'application_classification.application_profiles'." - ), + ) + raise AristaAvdInvalidInputsError(msg) + + append_dict_to_list_of_dicts( + list_of_dicts=application_profiles, new_dict=self.inputs.application_classification.application_profiles[application_profile]._as_dict() ) + output = {"application_profiles": application_profiles} # Now handle categories, applicaations categories = [] applications = [] + for application_profile in application_profiles: for category in get(application_profile, "categories", default=[]): - _append_object_to_list_of_dicts( - path="categories", - obj_name=category["name"], - list_of_dicts=categories, - message=( + if category["name"] not in self.inputs.application_classification.categories: + msg = ( f"The application profile {application_profile['name']} uses the category {category['name']} " "undefined in 'application_classification.categories'." - ), - ) + ) + raise AristaAvdInvalidInputsError(msg) + append_dict_to_list_of_dicts(new_dict=self.inputs.application_classification.categories[category["name"]]._as_dict(), list_of_dicts=categories) # Applications in application profiles for application in get(application_profile, "applications", default=[]): - _append_object_to_list_of_dicts( - path="applications.ipv4_applications", - obj_name=application["name"], - list_of_dicts=applications, - required=False, - ) + if application["name"] in self.inputs.application_classification.applications.ipv4_applications: + append_dict_to_list_of_dicts( + new_dict=self.inputs.application_classification.applications.ipv4_applications[application["name"]]._as_dict(), + list_of_dicts=applications, + ) # Applications in categories for category in categories: for application in get(category, "applications", default=[]): - _append_object_to_list_of_dicts( - path="applications.ipv4_applications", - obj_name=application["name"], - list_of_dicts=applications, - required=False, - ) + if application["name"] in self.inputs.application_classification.applications.ipv4_applications: + append_dict_to_list_of_dicts( + new_dict=self.inputs.application_classification.applications.ipv4_applications[application["name"]]._as_dict(), + list_of_dicts=applications, + ) + output["categories"] = categories # IPv4 only for now output["applications"] = {"ipv4_applications": applications} @@ -251,66 +224,29 @@ def _append_object_to_list_of_dicts(path: str, obj_name: str, list_of_dicts: lis l4_ports = [] ipv4_prefixes = [] for application in applications: - if (src_prefix_set_name := get(application, "src_prefix_set_name")) is not None: - _append_object_to_list_of_dicts( - path="field_sets.ipv4_prefixes", - obj_name=src_prefix_set_name, - list_of_dicts=ipv4_prefixes, - message=( - f"The IPv4 prefix field set {src_prefix_set_name} used in the application {application} " - "is undefined in 'application_classification.fields_sets.ipv4_prefixes'." - ), - ) - if (dest_prefix_set_name := get(application, "dest_prefix_set_name")) is not None: - _append_object_to_list_of_dicts( - path="field_sets.ipv4_prefixes", - obj_name=dest_prefix_set_name, - list_of_dicts=ipv4_prefixes, - message=( - f"The IPv4 prefix field set {dest_prefix_set_name} used in the application {application} " - "is undefined in 'application_classification.fields_sets.ipv4_prefixes'." - ), - ) - if (udp_src_port_set_name := get(application, "udp_src_port_set_name")) is not None: - _append_object_to_list_of_dicts( - path="field_sets.l4_ports", - obj_name=udp_src_port_set_name, - list_of_dicts=l4_ports, - message=( - f"The L4 Ports field set {udp_src_port_set_name} used in the application {application} " - "is undefined in 'application_classification.fields_sets.l4_ports'." - ), - ) - if (udp_dest_port_set_name := get(application, "udp_dest_port_set_name")) is not None: - _append_object_to_list_of_dicts( - path="field_sets.l4_ports", - obj_name=udp_dest_port_set_name, - list_of_dicts=l4_ports, - message=( - f"The L4 Ports field set {udp_dest_port_set_name} used in the application {application} " - "is undefined in 'application_classification.fields_sets.l4_ports'." - ), - ) - if (tcp_src_port_set_name := get(application, "tcp_src_port_set_name")) is not None: - _append_object_to_list_of_dicts( - path="field_sets.l4_ports", - obj_name=tcp_src_port_set_name, - list_of_dicts=l4_ports, - message=( - f"The L4 Ports field set {tcp_src_port_set_name} used in the application {application} " - "is undefined in 'application_classification.fields_sets.l4_ports'." - ), - ) - if (tcp_dest_port_set_name := get(application, "tcp_dest_port_set_name")) is not None: - _append_object_to_list_of_dicts( - path="field_sets.l4_ports", - obj_name=tcp_dest_port_set_name, - list_of_dicts=l4_ports, - message=( - f"The L4 Ports field set {tcp_dest_port_set_name} used in the application {application} " - "is undefined in 'application_classification.fields_sets.l4_ports'." - ), - ) + for prefix_set_key in ("src_prefix_set_name", "dest_prefix_set_name"): + if (prefix_set_name := get(application, prefix_set_key)) is not None: + if prefix_set_name not in self.inputs.application_classification.field_sets.ipv4_prefixes: + msg = ( + f"The IPv4 prefix field set {prefix_set_name} used in the application {application} " + "is undefined in 'application_classification.fields_sets.ipv4_prefixes'." + ) + raise AristaAvdInvalidInputsError(msg) + append_dict_to_list_of_dicts( + new_dict=self.inputs.application_classification.field_sets.ipv4_prefixes[prefix_set_name]._as_dict(), list_of_dicts=ipv4_prefixes + ) + + for port_set_key in ("udp_src_port_set_name", "udp_dest_port_set_name", "tcp_src_port_set_name", "tcp_dest_port_set_name"): + if (port_set_name := get(application, port_set_key)) is not None: + if port_set_name not in self.inputs.application_classification.field_sets.l4_ports: + msg = ( + f"The L4 Ports field set {port_set_name} used in the application {application} " + "is undefined in 'application_classification.fields_sets.l4_ports'." + ) + raise AristaAvdInvalidInputsError(msg) + append_dict_to_list_of_dicts( + new_dict=self.inputs.application_classification.field_sets.l4_ports[port_set_name]._as_dict(), list_of_dicts=l4_ports + ) output["field_sets"] = { "l4_ports": l4_ports, diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/dps_interfaces.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/dps_interfaces.py index ce85f42b094..cbc2240a696 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/dps_interfaces.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/dps_interfaces.py @@ -42,7 +42,7 @@ def dps_interfaces(self: AvdStructuredConfigNetworkServices) -> list | None: # TODO: do IPv6 when needed - for now no easy way in AVD to detect if this is needed # When needed - need a default value if different than IPv4 - if (dps_flow := self.shared_utils.get_flow_tracker(None, "dps_interfaces")) is not None: + if (dps_flow := self.shared_utils.get_flow_tracker(self.inputs.fabric_flow_tracking.dps_interfaces)) is not None: dps1["flow_tracker"] = dps_flow return [dps1] diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/eos_cli.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/eos_cli.py index 619bef247ec..32b0fca8f04 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/eos_cli.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/eos_cli.py @@ -31,7 +31,7 @@ def eos_cli(self: AvdStructuredConfigNetworkServices) -> str | None: if (eos_cli := get(self._hostvars, "eos_cli")) is not None: eos_clis.append(eos_cli) - eos_clis.extend(vrf["raw_eos_cli"] for tenant in self.shared_utils.filtered_tenants for vrf in tenant["vrfs"] if vrf.get("raw_eos_cli") is not None) + eos_clis.extend(vrf.raw_eos_cli for tenant in self.shared_utils.filtered_tenants for vrf in tenant.vrfs if vrf.raw_eos_cli is not None) if eos_clis: return "\n".join(eos_clis) diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/ethernet_interfaces.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/ethernet_interfaces.py index a299939a4e9..49cab1e01c6 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/ethernet_interfaces.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/ethernet_interfaces.py @@ -31,7 +31,7 @@ def ethernet_interfaces(self: AvdStructuredConfigNetworkServices) -> list | None Only used with L3 or L1 network services """ - if not (self.shared_utils.network_services_l3 or self.shared_utils.network_services_l1 or self.shared_utils.l3_interfaces): + if not (self.shared_utils.network_services_l3 or self.shared_utils.network_services_l1): return None ethernet_interfaces = [] @@ -39,46 +39,43 @@ def ethernet_interfaces(self: AvdStructuredConfigNetworkServices) -> list | None if self.shared_utils.network_services_l3: for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: + for vrf in tenant.vrfs: # The l3_interfaces has already been filtered in filtered_tenants # to only contain entries with our hostname - for l3_interface in vrf["l3_interfaces"]: - nodes_length = len(l3_interface["nodes"]) + for l3_interface in vrf.l3_interfaces: + nodes_length = len(l3_interface.nodes) if ( - len(l3_interface["interfaces"]) != nodes_length - or len(l3_interface["ip_addresses"]) != nodes_length - or ("descriptions" in l3_interface and "description" not in l3_interface and len(l3_interface["descriptions"]) != nodes_length) + len(l3_interface.interfaces) != nodes_length + or len(l3_interface.ip_addresses) != nodes_length + or (l3_interface.descriptions and len(l3_interface.descriptions) != nodes_length) ): msg = ( "Length of lists 'interfaces', 'nodes', 'ip_addresses' and 'descriptions' (if used) must match for l3_interfaces for" - f" {vrf['name']} in {tenant['name']}" + f" {vrf.name} in {tenant.name}" ) raise AristaAvdError(msg) - for node_index, node_name in enumerate(l3_interface["nodes"]): + for node_index, node_name in enumerate(l3_interface.nodes): if node_name != self.shared_utils.hostname: continue - interface_name = str(l3_interface["interfaces"][node_index]) + interface_name = l3_interface.interfaces[node_index] # if 'descriptions' is set, it is preferred - if (interface_descriptions := l3_interface.get("descriptions")) is not None: - interface_description = interface_descriptions[node_index] - else: - interface_description = l3_interface.get("description") + interface_description = l3_interface.descriptions[node_index] if l3_interface.descriptions else l3_interface.description interface = { "name": interface_name, "peer_type": "l3_interface", - "ip_address": l3_interface["ip_addresses"][node_index], - "mtu": l3_interface.get("mtu") if self.shared_utils.platform_settings_feature_support_per_interface_mtu else None, - "shutdown": not l3_interface.get("enabled", True), + "ip_address": l3_interface.ip_addresses[node_index], + "mtu": l3_interface.mtu if self.shared_utils.platform_settings.feature_support.per_interface_mtu else None, + "shutdown": not l3_interface.enabled, "description": interface_description, - "eos_cli": l3_interface.get("raw_eos_cli"), - "struct_cfg": l3_interface.get("structured_config"), - "flow_tracker": self.shared_utils.get_flow_tracker(l3_interface, "l3_interfaces"), + "eos_cli": l3_interface.raw_eos_cli, + "struct_cfg": l3_interface.structured_config._as_dict(strip_values=()) or None, + "flow_tracker": self.shared_utils.get_flow_tracker(l3_interface.flow_tracking), } - if self.shared_utils.fabric_sflow_l3_interfaces is not None: - interface["sflow"] = {"enable": self.shared_utils.fabric_sflow_l3_interfaces} + if self.inputs.fabric_sflow.l3_interfaces is not None: + interface["sflow"] = {"enable": self.inputs.fabric_sflow.l3_interfaces} if self._l3_interface_acls is not None: interface.update( @@ -93,7 +90,7 @@ def ethernet_interfaces(self: AvdStructuredConfigNetworkServices) -> list | None parent_interface_name, subif_id = interface_name.split(".", maxsplit=1) subif_parent_interface_names.add(parent_interface_name) - encapsulation_dot1q_vlans = l3_interface.get("encapsulation_dot1q_vlan", []) + encapsulation_dot1q_vlans = l3_interface.encapsulation_dot1q_vlan if len(encapsulation_dot1q_vlans) > node_index: interface["encapsulation_dot1q"] = {"vlan": encapsulation_dot1q_vlans[node_index]} else: @@ -101,31 +98,30 @@ def ethernet_interfaces(self: AvdStructuredConfigNetworkServices) -> list | None else: interface.update({"switchport": {"enabled": False}}) - if vrf["name"] != "default": - interface["vrf"] = vrf["name"] + if vrf.name != "default": + interface["vrf"] = vrf.name - if get(l3_interface, "ospf.enabled") is True and get(vrf, "ospf.enabled") is True: - interface["ospf_area"] = l3_interface["ospf"].get("area", "0.0.0.0") # noqa: S104 - interface["ospf_network_point_to_point"] = l3_interface["ospf"].get("point_to_point", False) - interface["ospf_cost"] = l3_interface["ospf"].get("cost") - ospf_authentication = l3_interface["ospf"].get("authentication") - if ospf_authentication == "simple" and (ospf_simple_auth_key := l3_interface["ospf"].get("simple_auth_key")) is not None: + if l3_interface.ospf.enabled and vrf.ospf.enabled: + interface["ospf_area"] = l3_interface.ospf.area + interface["ospf_network_point_to_point"] = l3_interface.ospf.point_to_point + interface["ospf_cost"] = l3_interface.ospf.cost + ospf_authentication = l3_interface.ospf.authentication + if ospf_authentication == "simple" and (ospf_simple_auth_key := l3_interface.ospf.simple_auth_key) is not None: interface["ospf_authentication"] = ospf_authentication interface["ospf_authentication_key"] = ospf_simple_auth_key elif ( - ospf_authentication == "message-digest" - and (ospf_message_digest_keys := l3_interface["ospf"].get("message_digest_keys")) is not None + ospf_authentication == "message-digest" and (ospf_message_digest_keys := l3_interface.ospf.message_digest_keys) is not None ): ospf_keys = [] for ospf_key in ospf_message_digest_keys: - if not ("id" in ospf_key and "key" in ospf_key): + if not (ospf_key.id and ospf_key.key): continue ospf_keys.append( { - "id": ospf_key["id"], - "hash_algorithm": ospf_key.get("hash_algorithm", "sha512"), - "key": ospf_key["key"], + "id": ospf_key.id, + "hash_algorithm": ospf_key.hash_algorithm, + "key": ospf_key.key, }, ) @@ -133,8 +129,8 @@ def ethernet_interfaces(self: AvdStructuredConfigNetworkServices) -> list | None interface["ospf_authentication"] = ospf_authentication interface["ospf_message_digest_keys"] = ospf_keys - if get(l3_interface, "pim.enabled"): - if not vrf.get("_evpn_l3_multicast_enabled"): + if l3_interface.pim.enabled: + if not getattr(vrf, "_evpn_l3_multicast_enabled", False): # Possibly the key was not set because `evpn_multicast` is not set to `true`. if not self.shared_utils.evpn_multicast: msg = ( @@ -144,20 +140,16 @@ def ethernet_interfaces(self: AvdStructuredConfigNetworkServices) -> list | None else: msg = ( f"'pim: enabled' set on l3_interface '{interface_name}' on '{self.shared_utils.hostname}' requires " - f"'evpn_l3_multicast.enabled: true' under VRF '{vrf['name']}' or Tenant '{tenant['name']}'" + f"'evpn_l3_multicast.enabled: true' under VRF '{vrf.name}' or Tenant '{tenant.name}'" ) - raise AristaAvdError( - msg, - ) + raise AristaAvdError(msg) - if not vrf.get("_pim_rp_addresses"): + if not getattr(vrf, "_pim_rp_addresses", None): msg = ( f"'pim: enabled' set on l3_interface '{interface_name}' on '{self.shared_utils.hostname}' requires at least one RP" - f" defined in pim_rp_addresses under VRF '{vrf['name']}' or Tenant '{tenant['name']}'" - ) - raise AristaAvdError( - msg, + f" defined in pim_rp_addresses under VRF '{vrf.name}' or Tenant '{tenant.name}'" ) + raise AristaAvdError(msg) interface["pim"] = {"ipv4": {"sparse_mode": True}} @@ -174,22 +166,21 @@ def ethernet_interfaces(self: AvdStructuredConfigNetworkServices) -> list | None if self.shared_utils.network_services_l1: for tenant in self.shared_utils.filtered_tenants: - if "point_to_point_services" not in tenant: + if not tenant.point_to_point_services: continue - for point_to_point_service in natural_sort(tenant["point_to_point_services"], "name"): - subifs = [subif for subif in point_to_point_service.get("subinterfaces", []) if subif.get("number") is not None] - for endpoint in point_to_point_service.get("endpoints", []): - if self.shared_utils.hostname not in endpoint.get("nodes", []): + for point_to_point_service in tenant.point_to_point_services._natural_sorted(): + for endpoint in point_to_point_service.endpoints: + if self.shared_utils.hostname not in endpoint.nodes: continue - for node_index, interface_name in enumerate(endpoint["interfaces"]): - if endpoint["nodes"][node_index] != self.shared_utils.hostname: + for node_index, interface_name in enumerate(endpoint.interfaces): + if endpoint.nodes[node_index] != self.shared_utils.hostname: continue - if (port_channel_mode := get(endpoint, "port_channel.mode")) in ["active", "on"]: - first_interface_index = list(endpoint["nodes"]).index(self.shared_utils.hostname) - first_interface_name = endpoint["interfaces"][first_interface_index] + if (port_channel_mode := endpoint.port_channel.mode) in ["active", "on"]: + first_interface_index = endpoint.nodes.index(self.shared_utils.hostname) + first_interface_name = endpoint.interfaces[first_interface_index] channel_group_id = int("".join(re.findall(r"\d", first_interface_name))) ethernet_interface = { "name": interface_name, @@ -212,18 +203,18 @@ def ethernet_interfaces(self: AvdStructuredConfigNetworkServices) -> list | None continue - if subifs: + if point_to_point_service.subinterfaces: # This is a subinterface so we need to ensure that the parent is created subif_parent_interface_names.add(interface_name) - for subif in subifs: - subif_name = f"{interface_name}.{subif['number']}" + for subif in point_to_point_service.subinterfaces: + subif_name = f"{interface_name}.{subif.number}" ethernet_interface = { "name": subif_name, "peer_type": "point_to_point_service", "encapsulation_vlan": { "client": { "encapsulation": "dot1q", - "vlan": subif["number"], + "vlan": subif.number, }, "network": { "encapsulation": "client", @@ -248,7 +239,7 @@ def ethernet_interfaces(self: AvdStructuredConfigNetworkServices) -> list | None "peer_type": "point_to_point_service", "shutdown": False, } - if point_to_point_service.get("lldp_disable") is True: + if point_to_point_service.lldp_disable: interface["lldp"] = { "transmit": False, "receive": False, @@ -279,11 +270,11 @@ def ethernet_interfaces(self: AvdStructuredConfigNetworkServices) -> list | None { "name": connection["source_interface"], "ip_nat": { - "service_profile": self.get_internet_exit_nat_profile_name(internet_exit_policy["type"]), + "service_profile": self.get_internet_exit_nat_profile_name(internet_exit_policy.type), }, } - for internet_exit_policy in self._filtered_internet_exit_policies - for connection in internet_exit_policy.get("connections", []) + for internet_exit_policy, connections in self._filtered_internet_exit_policies_and_connections + for connection in connections if connection["type"] == "ethernet" ) diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/ip_access_lists.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/ip_access_lists.py index b002f1f9bf1..d106ec91a97 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/ip_access_lists.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/ip_access_lists.py @@ -7,7 +7,7 @@ from typing import TYPE_CHECKING, Literal from pyavd._errors import AristaAvdError -from pyavd._utils import append_if_not_duplicate, get, get_ip_from_ip_prefix +from pyavd._utils import append_if_not_duplicate, get_ip_from_ip_prefix from pyavd.j2filters import natural_sort from .utils import UtilsMixin @@ -41,9 +41,9 @@ def _acl_internet_exit_zscaler(self: AvdStructuredConfigNetworkServices) -> dict @cached_property def _acl_internet_exit_direct(self: AvdStructuredConfigNetworkServices) -> dict | None: interface_ips = set() - for ie_policy in self._filtered_internet_exit_policies: - if ie_policy["type"] == "direct": - for connection in ie_policy["connections"]: + for ie_policy, connections in self._filtered_internet_exit_policies_and_connections: + if ie_policy.type == "direct": + for connection in connections: interface_ips.add(connection["source_interface_ip_address"]) if interface_ips: @@ -76,24 +76,24 @@ def _acl_internet_exit_direct(self: AvdStructuredConfigNetworkServices) -> dict } return None - def _acl_internet_exit_user_defined(self: AvdStructuredConfigNetworkServices, internet_exit_policy_type: Literal["zscaler", "direct"]) -> dict | None: + def _acl_internet_exit_user_defined(self: AvdStructuredConfigNetworkServices, internet_exit_policy_type: Literal["zscaler", "direct"]) -> list[dict] | None: acl_name = self.get_internet_exit_nat_acl_name(internet_exit_policy_type) - acl = get(self.shared_utils.ipv4_acls, acl_name) - if not acl: + if acl_name not in self.inputs.ipv4_acls: + # TODO: Evaluate if we should continue so we raise when there is no ACL. return None # pass substitution fields as anything to check if acl requires substitution or not acl = self.shared_utils.get_ipv4_acl(acl_name, "random", interface_ip="random", peer_ip="random") - if acl["name"] == acl_name: + if acl.name == acl_name: # ACL doesn't need replacement - return [acl] + return [acl._as_dict()] # TODO: We still have one nat for all interfaces, need to also add logic to make nat per interface # if acl needs substitution msg = f"ipv4_acls[name={acl_name}] field substitution is not supported for internet exit access lists" raise AristaAvdError(msg) - def _acl_internet_exit(self: AvdStructuredConfigNetworkServices, internet_exit_policy_type: Literal["zscaler", "direct"]) -> dict | None: + def _acl_internet_exit(self: AvdStructuredConfigNetworkServices, internet_exit_policy_type: Literal["zscaler", "direct"]) -> list[dict] | None: acls = self._acl_internet_exit_user_defined(internet_exit_policy_type) if acls: return acls diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/ip_igmp_snooping.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/ip_igmp_snooping.py index a0aaa6c3465..0809c347886 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/ip_igmp_snooping.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/ip_igmp_snooping.py @@ -6,11 +6,13 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import append_if_not_duplicate, default, get +from pyavd._utils import append_if_not_duplicate, default, strip_empties_from_dict from .utils import UtilsMixin if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + from . import AvdStructuredConfigNetworkServices @@ -27,26 +29,25 @@ def ip_igmp_snooping(self: AvdStructuredConfigNetworkServices) -> dict | None: if not self.shared_utils.network_services_l2: return None - ip_igmp_snooping = {} igmp_snooping_enabled = self.shared_utils.igmp_snooping_enabled - ip_igmp_snooping["globally_enabled"] = igmp_snooping_enabled - if igmp_snooping_enabled is not True: + ip_igmp_snooping = {"globally_enabled": igmp_snooping_enabled} + if not igmp_snooping_enabled: return ip_igmp_snooping vlans = [] for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: - for svi in vrf["svis"]: + for vrf in tenant.vrfs: + for svi in vrf.svis: if vlan := self._ip_igmp_snooping_vlan(svi, tenant): append_if_not_duplicate( list_of_dicts=vlans, primary_key="id", new_dict=vlan, - context=f"IGMP snooping for SVIs in VRF '{vrf['name']}'", + context=f"IGMP snooping for SVIs in VRF '{vrf.name}'", context_keys=["id"], ) - for l2vlan in tenant["l2vlans"]: + for l2vlan in tenant.l2vlans: if vlan := self._ip_igmp_snooping_vlan(l2vlan, tenant): append_if_not_duplicate( list_of_dicts=vlans, @@ -61,24 +62,21 @@ def ip_igmp_snooping(self: AvdStructuredConfigNetworkServices) -> dict | None: return ip_igmp_snooping - def _ip_igmp_snooping_vlan(self: AvdStructuredConfigNetworkServices, vlan: dict, tenant: dict) -> dict: + def _ip_igmp_snooping_vlan( + self: AvdStructuredConfigNetworkServices, + vlan: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem + | EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.L2vlansItem, + tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem, + ) -> dict: """ ip_igmp_snooping logic for one vlan. Can be used for both svis and l2vlans """ - tenant_igmp_snooping_querier = tenant.get("igmp_snooping_querier", {}) - igmp_snooping_querier = vlan.get("igmp_snooping_querier", {}) igmp_snooping_enabled = None igmp_snooping_querier_enabled = None - evpn_l2_multicast_enabled = ( - default( - get(vlan, "evpn_l2_multicast.enabled"), - get(tenant, "evpn_l2_multicast.enabled"), - ) - and self.shared_utils.evpn_multicast is True - ) - if self.shared_utils.overlay_vtep and evpn_l2_multicast_enabled is True: + evpn_l2_multicast_enabled = bool(default(vlan.evpn_l2_multicast.enabled, tenant.evpn_l2_multicast.enabled)) and self.shared_utils.evpn_multicast + if self.shared_utils.overlay_vtep and evpn_l2_multicast_enabled: # Leaving igmp_snooping_enabled unset, to avoid extra line of config as we already check # that global igmp snooping is enabled and igmp snooping is required for evpn_l2_multicast. @@ -87,41 +85,28 @@ def _ip_igmp_snooping_vlan(self: AvdStructuredConfigNetworkServices, vlan: dict, igmp_snooping_querier_enabled = True else: - igmp_snooping_enabled = vlan.get("igmp_snooping_enabled") + igmp_snooping_enabled = vlan.igmp_snooping_enabled if self.shared_utils.network_services_l3 and self.shared_utils.uplink_type in ["p2p", "p2p-vrfs"]: - igmp_snooping_querier_enabled = default( - igmp_snooping_querier.get("enabled"), - tenant_igmp_snooping_querier.get("enabled"), - ) - - ip_igmp_snooping_vlan = {} - if igmp_snooping_enabled is not None: - ip_igmp_snooping_vlan["enabled"] = igmp_snooping_enabled - - if igmp_snooping_querier_enabled is not None: - ip_igmp_snooping_vlan["querier"] = {"enabled": igmp_snooping_querier_enabled} - if igmp_snooping_querier_enabled is True: - address = default(igmp_snooping_querier.get("source_address"), tenant_igmp_snooping_querier.get("source_address"), self.shared_utils.router_id) - if address is not None: - ip_igmp_snooping_vlan["querier"]["address"] = address - - version = default( - igmp_snooping_querier.get("version"), - tenant_igmp_snooping_querier.get("version"), - ) - if version is not None: - ip_igmp_snooping_vlan["querier"]["version"] = version - - # IGMP snooping fast-leave feature is enabled only when evpn_l2_multicast is enabled - if evpn_l2_multicast_enabled is True: - fast_leave = default( - igmp_snooping_querier.get("fast_leave"), - get(tenant, "evpn_l2_multicast.fast_leave"), - ) - if fast_leave is not None: - ip_igmp_snooping_vlan["fast_leave"] = fast_leave + igmp_snooping_querier_enabled = default(vlan.igmp_snooping_querier.enabled, tenant.igmp_snooping_querier.enabled) + + ip_igmp_snooping_vlan = strip_empties_from_dict( + { + "enabled": igmp_snooping_enabled, + "querier": { + "enabled": igmp_snooping_querier_enabled, + "address": ( + default(vlan.igmp_snooping_querier.source_address, tenant.igmp_snooping_querier.source_address, self.shared_utils.router_id) + if igmp_snooping_querier_enabled + else None + ), + "version": default(vlan.igmp_snooping_querier.version, tenant.igmp_snooping_querier.version) if igmp_snooping_querier_enabled else None, + }, + # IGMP snooping fast-leave feature is enabled only when evpn_l2_multicast is enabled + "fast_leave": default(vlan.igmp_snooping_querier.fast_leave, tenant.evpn_l2_multicast.fast_leave) if evpn_l2_multicast_enabled else None, + } + ) if ip_igmp_snooping_vlan: - return {"id": int(vlan["id"]), **ip_igmp_snooping_vlan} + return {"id": vlan.id, **ip_igmp_snooping_vlan} return ip_igmp_snooping_vlan diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/ip_security.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/ip_security.py index 0a7644f52d5..843e72b3029 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/ip_security.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/ip_security.py @@ -6,7 +6,7 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import get, strip_null_from_data +from pyavd._utils import strip_null_from_data from .utils import UtilsMixin @@ -24,17 +24,17 @@ class IpSecurityMixin(UtilsMixin): @cached_property def ip_security(self: AvdStructuredConfigNetworkServices) -> dict | None: """ip_security set based on cv_pathfinder_internet_exit_policies.""" - if not self._filtered_internet_exit_policies: + if not self._filtered_internet_exit_policies_and_connections: return None ip_security = {"ike_policies": [], "sa_policies": [], "profiles": []} - for internet_exit_policy in self._filtered_internet_exit_policies: + for internet_exit_policy, _connections in self._filtered_internet_exit_policies_and_connections: # Currently we only need ipsec for zscaler. - if internet_exit_policy["type"] != "zscaler": + if internet_exit_policy.type != "zscaler": continue - policy_name = internet_exit_policy["name"] - encrypt_traffic = get(internet_exit_policy, "zscaler.encrypt_traffic", default=True) + policy_name = internet_exit_policy.name + encrypt_traffic = internet_exit_policy.zscaler.encrypt_traffic ike_policy_name = f"IE-{policy_name}-IKE-POLICY" sa_policy_name = f"IE-{policy_name}-SA-POLICY" profile_name = f"IE-{policy_name}-PROFILE" diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/ip_virtual_router_mac_address.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/ip_virtual_router_mac_address.py index 93b653e9339..0a0a942165a 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/ip_virtual_router_mac_address.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/ip_virtual_router_mac_address.py @@ -22,7 +22,11 @@ class IpVirtualRouterMacAddressMixin(UtilsMixin): @cached_property def ip_virtual_router_mac_address(self: AvdStructuredConfigNetworkServices) -> str | None: """Return structured config for ip_virtual_router_mac_address.""" - if self.shared_utils.network_services_l2 and self.shared_utils.network_services_l3 and self.shared_utils.virtual_router_mac_address is not None: - return str(self.shared_utils.virtual_router_mac_address).lower() + if ( + self.shared_utils.network_services_l2 + and self.shared_utils.network_services_l3 + and self.shared_utils.node_config.virtual_router_mac_address is not None + ): + return str(self.shared_utils.node_config.virtual_router_mac_address).lower() return None diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/ipv6_static_routes.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/ipv6_static_routes.py index bb27ab6d4fa..0fe4fc6d394 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/ipv6_static_routes.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/ipv6_static_routes.py @@ -33,14 +33,15 @@ def ipv6_static_routes(self: AvdStructuredConfigNetworkServices) -> list[dict] | ipv6_static_routes = [] for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: - for static_route in vrf["ipv6_static_routes"]: - static_route["vrf"] = vrf["name"] - static_route.pop("nodes", None) + for vrf in tenant.vrfs: + for static_route in vrf.ipv6_static_routes: + ipv6_static_route = static_route._as_dict() + ipv6_static_route["vrf"] = vrf.name + ipv6_static_route.pop("nodes", None) # Ignore duplicate items in case of duplicate VRF definitions across multiple tenants. if static_route not in ipv6_static_routes: - ipv6_static_routes.append(static_route) + ipv6_static_routes.append(ipv6_static_route) if ipv6_static_routes: return ipv6_static_routes diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/loopback_interfaces.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/loopback_interfaces.py index 723487bc8b6..ff330de0eef 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/loopback_interfaces.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/loopback_interfaces.py @@ -6,11 +6,13 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import AvdStringFormatter, append_if_not_duplicate, get, get_item +from pyavd._utils import AvdStringFormatter, append_if_not_duplicate, default, strip_empties_from_dict from .utils import UtilsMixin if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + from . import AvdStructuredConfigNetworkServices @@ -34,7 +36,7 @@ def loopback_interfaces(self: AvdStructuredConfigNetworkServices) -> list | None loopback_interfaces = [] for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: + for vrf in tenant.vrfs: if (loopback_interface := self._get_vtep_diagnostic_loopback_for_vrf(vrf)) is not None: append_if_not_duplicate( list_of_dicts=loopback_interfaces, @@ -47,20 +49,20 @@ def loopback_interfaces(self: AvdStructuredConfigNetworkServices) -> list | None # The loopbacks have already been filtered in _filtered_tenants # to only contain entries with our hostname - for loopback in vrf["loopbacks"]: + for loopback in vrf.loopbacks: loopback_interface = { - "name": f"Loopback{loopback['loopback']}", - "ip_address": loopback.get("ip_address"), - "shutdown": not loopback.get("enabled", True), - "description": loopback.get("description"), - "eos_cli": loopback.get("raw_eos_cli"), + "name": f"Loopback{loopback.loopback}", + "ip_address": loopback.ip_address, + "shutdown": not loopback.enabled, + "description": loopback.description, + "eos_cli": loopback.raw_eos_cli, } - if vrf["name"] != "default": - loopback_interface["vrf"] = vrf["name"] + if vrf.name != "default": + loopback_interface["vrf"] = vrf.name - if get(loopback, "ospf.enabled") is True and get(vrf, "ospf.enabled") is True: - loopback_interface["ospf_area"] = loopback["ospf"].get("area", "0.0.0.0") # noqa: S104 + if loopback.ospf.enabled and vrf.ospf.enabled: + loopback_interface["ospf_area"] = loopback.ospf.area # Strip None values from interface before adding to list loopback_interface = {key: value for key, value in loopback_interface.items() if value is not None} @@ -77,33 +79,32 @@ def loopback_interfaces(self: AvdStructuredConfigNetworkServices) -> list | None return None - def _get_vtep_diagnostic_loopback_for_vrf(self: AvdStructuredConfigNetworkServices, vrf: dict) -> dict | None: - if (loopback := get(vrf, "vtep_diagnostic.loopback")) is None: + def _get_vtep_diagnostic_loopback_for_vrf( + self: AvdStructuredConfigNetworkServices, vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem + ) -> dict | None: + if (loopback := vrf.vtep_diagnostic.loopback) is None: return None - pod_name = self.shared_utils.pod_name - loopback_ip_pools = get(vrf, "vtep_diagnostic.loopback_ip_pools") - if ((loopback_ipv4_pool := get(vrf, "vtep_diagnostic.loopback_ip_range")) is None) and pod_name and loopback_ip_pools: - loopback_ipv4_pool = get_item(loopback_ip_pools, "pod", pod_name, default={}).get("ipv4_pool") + pod_name = self.inputs.pod_name + loopback_ip_pools = vrf.vtep_diagnostic.loopback_ip_pools + if not (loopback_ipv4_pool := vrf.vtep_diagnostic.loopback_ip_range) and pod_name and loopback_ip_pools and pod_name in loopback_ip_pools: + loopback_ipv4_pool = loopback_ip_pools[pod_name].ipv4_pool - if ((loopback_ipv6_pool := get(vrf, "vtep_diagnostic.loopback_ipv6_range")) is None) and pod_name and loopback_ip_pools: - loopback_ipv6_pool = get_item(loopback_ip_pools, "pod", pod_name, default={}).get("ipv6_pool") + if not (loopback_ipv6_pool := vrf.vtep_diagnostic.loopback_ipv6_range) and pod_name and loopback_ip_pools and pod_name in loopback_ip_pools: + loopback_ipv6_pool = loopback_ip_pools[pod_name].ipv6_pool if not loopback_ipv4_pool and not loopback_ipv6_pool: return None interface_name = f"Loopback{loopback}" - description_template = get(vrf, "vtep_diagnostic.loopback_description", default=self.shared_utils.default_vrf_diag_loopback_description) - vtep_diagnostic_loopback_for_vrf = { - "name": interface_name, - "description": AvdStringFormatter().format(description_template, interface=interface_name, vrf=vrf["name"], tenant=vrf["tenant"]), - "shutdown": False, - "vrf": vrf["name"], - } - - if loopback_ipv4_pool: - vtep_diagnostic_loopback_for_vrf["ip_address"] = f"{self.shared_utils.ip_addressing.vrf_loopback_ip(loopback_ipv4_pool)}/32" - if loopback_ipv6_pool: - vtep_diagnostic_loopback_for_vrf["ipv6_address"] = f"{self.shared_utils.ip_addressing.vrf_loopback_ipv6(loopback_ipv6_pool)}/128" - - return vtep_diagnostic_loopback_for_vrf + description_template = default(vrf.vtep_diagnostic.loopback_description, self.inputs.default_vrf_diag_loopback_description) + return strip_empties_from_dict( + { + "name": interface_name, + "description": AvdStringFormatter().format(description_template, interface=interface_name, vrf=vrf.name, tenant=vrf._tenant), + "shutdown": False, + "vrf": vrf.name, + "ip_address": f"{self.shared_utils.ip_addressing.vrf_loopback_ip(loopback_ipv4_pool)}/32" if loopback_ipv4_pool else None, + "ipv6_address": f"{self.shared_utils.ip_addressing.vrf_loopback_ipv6(loopback_ipv6_pool)}/128" if loopback_ipv6_pool else None, + } + ) diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/metadata.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/metadata.py index a82cfc80479..47bf196f85c 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/metadata.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/metadata.py @@ -43,29 +43,29 @@ def metadata(self: AvdStructuredConfigNetworkServices) -> dict | None: return {"cv_pathfinder": cv_pathfinder_metadata} - def get_cv_pathfinder_metadata_internet_exit_policies(self: AvdStructuredConfigNetworkServices) -> dict | None: + def get_cv_pathfinder_metadata_internet_exit_policies(self: AvdStructuredConfigNetworkServices) -> list[dict] | None: """Generate metadata.cv_pathfinder.internet_exit_policies if available.""" - if not self._filtered_internet_exit_policies: + if not self._filtered_internet_exit_policies_and_connections: return None internet_exit_polices = [] - for internet_exit_policy in self._filtered_internet_exit_policies: + for internet_exit_policy, connections in self._filtered_internet_exit_policies_and_connections: # Currently only supporting zscaler - if internet_exit_policy["type"] != "zscaler": + if internet_exit_policy.type != "zscaler": continue ufqdn, ipsec_key = self._get_ipsec_credentials(internet_exit_policy) internet_exit_polices.append( { - "name": internet_exit_policy["name"], - "type": internet_exit_policy["type"], - "city": get(self._zscaler_endpoints, "device_location.city", required=True, org_key="zscaler_endpoints.device_location.city"), - "country": get(self._zscaler_endpoints, "device_location.country", required=True, org_key="zscaler_endpoints.device_location.country"), - "upload_bandwidth": get(internet_exit_policy, "zscaler.upload_bandwidth"), - "download_bandwidth": get(internet_exit_policy, "zscaler.download_bandwidth"), - "firewall": get(internet_exit_policy, "zscaler.firewall.enabled", default=False), - "ips_control": get(internet_exit_policy, "zscaler.firewall.ips", default=False), - "acceptable_use_policy": get(internet_exit_policy, "zscaler.acceptable_use_policy", default=False), + "name": internet_exit_policy.name, + "type": internet_exit_policy.type, + "city": self._zscaler_endpoints.device_location.city, + "country": self._zscaler_endpoints.device_location.country, + "upload_bandwidth": internet_exit_policy.zscaler.upload_bandwidth, + "download_bandwidth": internet_exit_policy.zscaler.download_bandwidth, + "firewall": internet_exit_policy.zscaler.firewall.enabled, + "ips_control": internet_exit_policy.zscaler.firewall.ips, + "acceptable_use_policy": internet_exit_policy.zscaler.acceptable_use_policy, "vpn_credentials": [ { "fqdn": ufqdn, @@ -79,7 +79,7 @@ def get_cv_pathfinder_metadata_internet_exit_policies(self: AvdStructuredConfigN "preference": "Preferred" if connection["preference"] == "primary" else "Alternate", "endpoint": connection["endpoint"], } - for connection in internet_exit_policy["connections"] + for connection in connections ], }, ) diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/monitor_connectivity.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/monitor_connectivity.py index dbd446c9d98..0f3727364fe 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/monitor_connectivity.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/monitor_connectivity.py @@ -28,15 +28,15 @@ def monitor_connectivity(self: AvdStructuredConfigNetworkServices) -> dict | Non Only used for CV Pathfinder edge routers today """ - if not self._filtered_internet_exit_policies: + if not self._filtered_internet_exit_policies_and_connections: return None monitor_connectivity = {} interface_sets = [] hosts = [] - for policy in self._filtered_internet_exit_policies: - for connection in policy["connections"]: + for _policy, connections in self._filtered_internet_exit_policies_and_connections: + for connection in connections: interface_name = f"Tunnel{connection['tunnel_id']}" if connection["type"] == "tunnel" else connection["source_interface"] interface_set_name = f"SET-{self.shared_utils.sanitize_interface_name(interface_name)}" diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/patch_panel.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/patch_panel.py index 6333e5d60b5..8278ba1cc50 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/patch_panel.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/patch_panel.py @@ -7,8 +7,7 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import append_if_not_duplicate, get -from pyavd.j2filters import natural_sort +from pyavd._utils import append_if_not_duplicate from .utils import UtilsMixin @@ -31,41 +30,40 @@ def patch_panel(self: AvdStructuredConfigNetworkServices) -> dict | None: patches = [] for tenant in self.shared_utils.filtered_tenants: - if "point_to_point_services" not in tenant: + if not tenant.point_to_point_services: continue - for point_to_point_service in natural_sort(tenant["point_to_point_services"], "name"): - if subifs := point_to_point_service.get("subinterfaces", []): - subifs = [subif for subif in subifs if subif.get("number") is not None] - for endpoint in point_to_point_service.get("endpoints", []): - if self.shared_utils.hostname not in endpoint.get("nodes", []): + for point_to_point_service in tenant.point_to_point_services._natural_sorted(): + for endpoint in point_to_point_service.endpoints: + if self.shared_utils.hostname not in endpoint.nodes: continue - node_index = list(endpoint["nodes"]).index(self.shared_utils.hostname) - interface = endpoint["interfaces"][node_index] - if get(endpoint, "port_channel.mode") in ["active", "on"]: + node_index = endpoint.nodes.index(self.shared_utils.hostname) + interface = endpoint.interfaces[node_index] + if endpoint.port_channel.mode in ["active", "on"]: channel_group_id = "".join(re.findall(r"\d", interface)) interface = f"Port-Channel{channel_group_id}" - if subifs: - for subif in subifs: + # TODO: refactor this by inverting if and else condition and using continue at the end of the if + if point_to_point_service.subinterfaces: + for subif in point_to_point_service.subinterfaces: patch = { - "name": f"{point_to_point_service['name']}_{subif['number']}", + "name": f"{point_to_point_service.name}_{subif.number}", "enabled": True, "connectors": [ { "id": "1", "type": "interface", - "endpoint": f"{interface}.{subif['number']}", + "endpoint": f"{interface}.{subif.number}", }, ], } - if point_to_point_service.get("type") == "vpws-pseudowire": + if point_to_point_service.type == "vpws-pseudowire": patch["connectors"].append( { "id": "2", "type": "pseudowire", - "endpoint": f"bgp vpws {tenant['name']} pseudowire {point_to_point_service['name']}_{subif['number']}", + "endpoint": f"bgp vpws {tenant.name} pseudowire {point_to_point_service.name}_{subif.number}", }, ) append_if_not_duplicate( @@ -77,7 +75,7 @@ def patch_panel(self: AvdStructuredConfigNetworkServices) -> dict | None: ) else: patch = { - "name": f"{point_to_point_service['name']}", + "name": f"{point_to_point_service.name}", "enabled": True, "connectors": [ { @@ -87,12 +85,12 @@ def patch_panel(self: AvdStructuredConfigNetworkServices) -> dict | None: }, ], } - if point_to_point_service.get("type") == "vpws-pseudowire": + if point_to_point_service.type == "vpws-pseudowire": patch["connectors"].append( { "id": "2", "type": "pseudowire", - "endpoint": f"bgp vpws {tenant['name']} pseudowire {point_to_point_service['name']}", + "endpoint": f"bgp vpws {tenant.name} pseudowire {point_to_point_service.name}", }, ) append_if_not_duplicate( diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/port_channel_interfaces.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/port_channel_interfaces.py index 458acc5f53d..efe0a559455 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/port_channel_interfaces.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/port_channel_interfaces.py @@ -7,8 +7,7 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import append_if_not_duplicate, get, short_esi_to_route_target -from pyavd.j2filters import natural_sort +from pyavd._utils import append_if_not_duplicate, short_esi_to_route_target from .utils import UtilsMixin @@ -38,24 +37,22 @@ def port_channel_interfaces(self: AvdStructuredConfigNetworkServices) -> list | subif_parent_interfaces = [] for tenant in self.shared_utils.filtered_tenants: - if "point_to_point_services" not in tenant: + if not tenant.point_to_point_services: continue - for point_to_point_service in natural_sort(tenant["point_to_point_services"], "name"): - if subifs := point_to_point_service.get("subinterfaces", []): - subifs = [subif for subif in subifs if subif.get("number") is not None] - for endpoint in point_to_point_service.get("endpoints", []): - if self.shared_utils.hostname not in endpoint.get("nodes", []): + for point_to_point_service in tenant.point_to_point_services._natural_sorted(): + for endpoint in point_to_point_service.endpoints: + if self.shared_utils.hostname not in endpoint.nodes: continue - node_index = list(endpoint["nodes"]).index(self.shared_utils.hostname) - interface_name = endpoint["interfaces"][node_index] - if (port_channel_mode := get(endpoint, "port_channel.mode")) not in ["active", "on"]: + node_index = endpoint.nodes.index(self.shared_utils.hostname) + interface_name = endpoint.interfaces[node_index] + if (port_channel_mode := endpoint.port_channel.mode) not in ["active", "on"]: continue channel_group_id = "".join(re.findall(r"\d", interface_name)) interface_name = f"Port-Channel{channel_group_id}" - if subifs: + if point_to_point_service.subinterfaces: # This is a subinterface so we need to ensure that the parent is created parent_interface = { "name": interface_name, @@ -63,11 +60,11 @@ def port_channel_interfaces(self: AvdStructuredConfigNetworkServices) -> list | "peer_type": "system", "shutdown": False, } - if (short_esi := get(endpoint, "port_channel.short_esi")) is not None and len(short_esi.split(":")) == 3: + if (short_esi := endpoint.port_channel.short_esi) is not None and len(short_esi.split(":")) == 3: parent_interface.update( { "evpn_ethernet_segment": { - "identifier": f"{self.shared_utils.evpn_short_esi_prefix}{short_esi}", + "identifier": f"{self.inputs.evpn_short_esi_prefix}{short_esi}", "route_target": short_esi_to_route_target(short_esi), }, }, @@ -77,8 +74,8 @@ def port_channel_interfaces(self: AvdStructuredConfigNetworkServices) -> list | subif_parent_interfaces.append(parent_interface) - for subif in subifs: - subif_name = f"{interface_name}.{subif['number']}" + for subif in point_to_point_service.subinterfaces: + subif_name = f"{interface_name}.{subif.number}" port_channel_interface = { "name": subif_name, @@ -86,7 +83,7 @@ def port_channel_interfaces(self: AvdStructuredConfigNetworkServices) -> list | "encapsulation_vlan": { "client": { "encapsulation": "dot1q", - "vlan": subif["number"], + "vlan": subif.number, }, "network": { "encapsulation": "client", @@ -110,17 +107,17 @@ def port_channel_interfaces(self: AvdStructuredConfigNetworkServices) -> list | "peer_type": "point_to_point_service", "shutdown": False, } - if point_to_point_service.get("lldp_disable") is True: + if point_to_point_service.lldp_disable: interface["lldp"] = { "transmit": False, "receive": False, } - if (short_esi := get(endpoint, "port_channel.short_esi")) is not None and len(short_esi.split(":")) == 3: + if (short_esi := endpoint.port_channel.short_esi) is not None and len(short_esi.split(":")) == 3: interface.update( { "evpn_ethernet_segment": { - "identifier": f"{self.shared_utils.evpn_short_esi_prefix}{short_esi}", + "identifier": f"{self.inputs.evpn_short_esi_prefix}{short_esi}", "route_target": short_esi_to_route_target(short_esi), }, }, diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/prefix_lists.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/prefix_lists.py index ca1ad06f5d2..9a3c081c390 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/prefix_lists.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/prefix_lists.py @@ -77,7 +77,7 @@ def _mlag_ibgp_peering_subnets_without_redistribution(self: AvdStructuredConfigN """Return sorted list of MLAG peerings for VRFs where MLAG iBGP peering should not be redistributed.""" mlag_prefixes = set() for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: + for vrf in tenant.vrfs: if self._mlag_ibgp_peering_vlan_vrf(vrf, tenant) is None: continue diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/route_maps.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/route_maps.py index 008af9685c5..7752b439517 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/route_maps.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/route_maps.py @@ -37,16 +37,16 @@ def route_maps(self: AvdStructuredConfigNetworkServices) -> list | None: route_maps = [] for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: + for vrf in tenant.vrfs: # BGP Peers are already filtered in filtered_tenants # so we only have entries with our hostname in them. - for bgp_peer in vrf["bgp_peers"]: - ipv4_next_hop = bgp_peer.get("set_ipv4_next_hop") - ipv6_next_hop = bgp_peer.get("set_ipv6_next_hop") + for bgp_peer in vrf.bgp_peers: + ipv4_next_hop = bgp_peer.set_ipv4_next_hop + ipv6_next_hop = bgp_peer.set_ipv6_next_hop if ipv4_next_hop is None and ipv6_next_hop is None: continue - route_map_name = f"RM-{vrf['name']}-{bgp_peer['ip_address']}-SET-NEXT-HOP-OUT" + route_map_name = f"RM-{vrf.name}-{bgp_peer.ip_address}-SET-NEXT-HOP-OUT" set_action = f"ip next-hop {ipv4_next_hop}" if ipv4_next_hop is not None else f"ipv6 next-hop {ipv6_next_hop}" route_map = { @@ -70,7 +70,7 @@ def route_maps(self: AvdStructuredConfigNetworkServices) -> list | None: if (route_maps_vrf_default := self._route_maps_vrf_default) is not None: route_maps.extend(route_maps_vrf_default) - if self._configure_bgp_mlag_peer_group and self.shared_utils.mlag_ibgp_origin_incomplete: + if self._configure_bgp_mlag_peer_group and self.shared_utils.node_config.mlag_ibgp_origin_incomplete: route_maps.append(self._bgp_mlag_peer_group_route_map()) if self._mlag_ibgp_peering_subnets_without_redistribution: @@ -239,7 +239,7 @@ def _redistribute_connected_to_bgp_route_map(self: AvdStructuredConfigNetworkSer sequence 10 is set in underlay and sequence 20 in inband management, so avoid setting those here """ - if not self.shared_utils.underlay_filter_redistribute_connected: + if not self.inputs.underlay_filter_redistribute_connected: return None sequence_numbers = [] diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/router_adaptive_virtual_topology.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/router_adaptive_virtual_topology.py index ffed157b70e..0a6007fe19c 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/router_adaptive_virtual_topology.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/router_adaptive_virtual_topology.py @@ -41,7 +41,7 @@ def _cv_pathfinder_wan_vrfs(self: AvdStructuredConfigNetworkServices) -> list: wan_vrfs = [] for vrf in self._filtered_wan_vrfs: - wan_vrf = {"name": vrf["name"], "policy": vrf["policy"], "profiles": []} + wan_vrf = {"name": vrf.name, "policy": f"{vrf.policy}-WITH-CP" if vrf.name == "default" else vrf.policy, "profiles": []} # Need to allocate an ID for each profile in the policy, for now picked up from the input. policy = get_item( @@ -110,11 +110,9 @@ def _cv_pathfinder_profiles(self: AvdStructuredConfigNetworkServices) -> list: "name": match["avt_profile"], "load_balance_policy": match["load_balance_policy"]["name"], } - if (internet_exit_policy_name := match["internet_exit_policy_name"]) is not None and get_item( - self._filtered_internet_exit_policies, - "name", - internet_exit_policy_name, - ) is not None: + if (internet_exit_policy_name := match["internet_exit_policy_name"]) is not None and internet_exit_policy_name in [ + policy.name for policy, _connections in self._filtered_internet_exit_policies_and_connections + ]: profile["internet_exit_policy"] = internet_exit_policy_name append_if_not_duplicate( @@ -129,11 +127,9 @@ def _cv_pathfinder_profiles(self: AvdStructuredConfigNetworkServices) -> list: "name": default_match["avt_profile"], "load_balance_policy": default_match["load_balance_policy"]["name"], } - if (internet_exit_policy_name := default_match["internet_exit_policy_name"]) is not None and get_item( - self._filtered_internet_exit_policies, - "name", - internet_exit_policy_name, - ) is not None: + if (internet_exit_policy_name := default_match["internet_exit_policy_name"]) is not None and internet_exit_policy_name in [ + policy.name for policy, _connections in self._filtered_internet_exit_policies_and_connections + ]: profile["internet_exit_policy"] = internet_exit_policy_name append_if_not_duplicate( diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/router_bgp.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/router_bgp.py index 94c204ef1e7..8d26e868441 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/router_bgp.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/router_bgp.py @@ -6,12 +6,12 @@ import ipaddress from functools import cached_property from itertools import groupby as itertools_groupby -from re import fullmatch as re_fullmatch from typing import TYPE_CHECKING +from pyavd._eos_designs.schema import EosDesigns from pyavd._errors import AristaAvdInvalidInputsError -from pyavd._utils import AvdStringFormatter, append_if_not_duplicate, default, get, get_item, merge, strip_empties_from_dict -from pyavd.j2filters import list_compress, natural_sort +from pyavd._utils import AvdStringFormatter, append_if_not_duplicate, default, get_item, merge, strip_empties_from_dict +from pyavd.j2filters import list_compress from .utils import UtilsMixin @@ -73,60 +73,56 @@ def _router_bgp_peer_groups(self: AvdStructuredConfigNetworkServices) -> dict: if not self.shared_utils.network_services_l3: return {} - peer_groups = [] + peer_groups: list[EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.BgpPeerGroupsItem] = [] peer_peergroups = set() for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: + for vrf in tenant.vrfs: # bgp_peers is already filtered in filtered_tenants to only contain entries with our hostname - if not (vrf["bgp_peers"] or vrf.get("bgp_peer_groups")): + if not (vrf.bgp_peers or vrf.bgp_peer_groups): continue - vrf_peer_peergroups = {peer["peer_group"] for peer in vrf["bgp_peers"] if "peer_group" in peer} + vrf_peer_peergroups = {peer.peer_group for peer in vrf.bgp_peers if peer.peer_group} peer_groups.extend( [ peer_group - for peer_group in vrf.get("bgp_peer_groups", []) - if (self.shared_utils.hostname in peer_group.get("nodes", []) or peer_group["name"] in vrf_peer_peergroups) + for peer_group in vrf.bgp_peer_groups + if self.shared_utils.hostname in peer_group.nodes or peer_group.name in vrf_peer_peergroups ], ) peer_peergroups.update(vrf_peer_peergroups) peer_groups.extend( - [ - peer_group - for peer_group in tenant.get("bgp_peer_groups", []) - if (self.shared_utils.hostname in peer_group.get("nodes", []) or peer_group["name"] in peer_peergroups) - ], + [peer_group for peer_group in tenant.bgp_peer_groups if self.shared_utils.hostname in peer_group.nodes or peer_group.name in peer_peergroups], ) router_bgp = {"peer_groups": []} - if peer_groups: - for peer_group in peer_groups: - peer_group.pop("nodes", None) - for af in ["address_family_ipv4", "address_family_ipv6"]: - if not (af_peer_group := peer_group.pop(af, None)): - continue - af_peer_groups = router_bgp.setdefault(af, {"peer_groups": []})["peer_groups"] - append_if_not_duplicate( - primary_key="name", - list_of_dicts=af_peer_groups, - new_dict={"name": peer_group["name"], **af_peer_group}, - context=f"BGP Peer Groups for '{af}' defined under network services", - context_keys=["name"], - ) + for peer_group in peer_groups: + peer_group_dict = peer_group._as_dict() + peer_group_dict.pop("nodes", None) + for af in ["address_family_ipv4", "address_family_ipv6"]: + if not (af_peer_group := peer_group_dict.pop(af, None)): + continue + af_peer_groups = router_bgp.setdefault(af, {"peer_groups": []})["peer_groups"] append_if_not_duplicate( - list_of_dicts=router_bgp["peer_groups"], primary_key="name", - new_dict=peer_group, - context="BGP Peer Groups defined under network services", + list_of_dicts=af_peer_groups, + new_dict={"name": peer_group_dict["name"], **af_peer_group}, + context=f"BGP Peer Groups for '{af}' defined under network services", context_keys=["name"], ) + append_if_not_duplicate( + list_of_dicts=router_bgp["peer_groups"], + primary_key="name", + new_dict=peer_group_dict, + context="BGP Peer Groups defined under network services", + context_keys=["name"], + ) # router bgp default vrf configuration for evpn if self._vrf_default_evpn and (self._vrf_default_ipv4_subnets or self._vrf_default_ipv4_static_routes["static_routes"]): router_bgp["peer_groups"].append( { - "name": self.shared_utils.bgp_peer_groups["ipv4_underlay_peers"]["name"], + "name": self.inputs.bgp_peer_groups.ipv4_underlay_peers.name, "type": "ipv4", "route_map_out": "RM-BGP-UNDERLAY-PEERS-OUT", }, @@ -149,35 +145,32 @@ def _router_bgp_vrfs(self: AvdStructuredConfigNetworkServices) -> dict: router_bgp = {"vrfs": []} for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: + for vrf in tenant.vrfs: if not self.shared_utils.bgp_enabled_for_vrf(vrf): continue - vrf_name = vrf["name"] + vrf_name = vrf.name bgp_vrf = strip_empties_from_dict( { - "eos_cli": get(vrf, "bgp.raw_eos_cli"), - "struct_cfg": get(vrf, "bgp.structured_config"), + "eos_cli": vrf.bgp.raw_eos_cli, + "struct_cfg": vrf.bgp.structured_config._as_dict(strip_values=()) or None, } ) - if vrf_address_families := [af for af in vrf.get("address_families", ["evpn"]) if af in self.shared_utils.overlay_address_families]: + if vrf_address_families := [af for af in vrf.address_families if af in self.shared_utils.overlay_address_families]: # The called function in-place updates the bgp_vrf dict. self._update_router_bgp_vrf_evpn_or_mpls_cfg(bgp_vrf, vrf, vrf_address_families) - bgp_vrf_redistribute_connected = get(vrf, "redistribute_connected", default=True) if vrf_name != "default": # Non-default VRF - if not self.shared_utils.use_router_general_for_router_id: + if not self.inputs.use_router_general_for_router_id: bgp_vrf["router_id"] = self.shared_utils.router_id - if bgp_vrf_redistribute_connected is True: + if vrf.redistribute_connected: bgp_vrf["redistribute"] = {"connected": {"enabled": True}} # Redistribution of static routes for VRF default are handled elsewhere # since there is a choice between redistributing to underlay or overlay. - if (bgp_vrf_redistribute_static := vrf.get("redistribute_static")) is True or ( - vrf["static_routes"] and bgp_vrf_redistribute_static is not False - ): + if vrf.redistribute_static or (vrf.static_routes and vrf.redistribute_static is None): bgp_vrf["redistribute"].update({"static": {"enabled": True}}) if self.shared_utils.inband_mgmt_vrf == vrf_name and self.shared_utils.inband_management_parent_vlans: @@ -207,19 +200,20 @@ def _router_bgp_vrfs(self: AvdStructuredConfigNetworkServices) -> dict: if (vlan_id := self._mlag_ibgp_peering_vlan_vrf(vrf, tenant)) is not None: self._update_router_bgp_vrf_mlag_neighbor_cfg(bgp_vrf, vrf, tenant, vlan_id) - for bgp_peer in vrf["bgp_peers"]: + for bgp_peer in vrf.bgp_peers: # Below we pop various keys that are not supported by the eos_cli_config_gen schema. # The rest of the keys are relayed directly to eos_cli_config_gen. # 'ip_address' is popped even though it is supported. It will be added again later # to ensure it comes first in the generated dict. - peer_ip = bgp_peer.pop("ip_address") + bgp_peer_dict = bgp_peer._as_dict() + peer_ip = bgp_peer_dict.pop("ip_address") address_family = f"address_family_ipv{ipaddress.ip_address(peer_ip).version}" neighbor = strip_empties_from_dict( { "ip_address": peer_ip, "activate": True, - "prefix_list_in": bgp_peer.pop("prefix_list_in", None), - "prefix_list_out": bgp_peer.pop("prefix_list_out", None), + "prefix_list_in": bgp_peer_dict.pop("prefix_list_in", None), + "prefix_list_out": bgp_peer_dict.pop("prefix_list_out", None), }, ) @@ -231,36 +225,34 @@ def _router_bgp_vrfs(self: AvdStructuredConfigNetworkServices) -> dict: context_keys=["ip_address"], ) - if bgp_peer.get("set_ipv4_next_hop") is not None or bgp_peer.get("set_ipv6_next_hop") is not None: + if bgp_peer.set_ipv4_next_hop or bgp_peer.set_ipv6_next_hop: route_map = f"RM-{vrf_name}-{peer_ip}-SET-NEXT-HOP-OUT" - bgp_peer["route_map_out"] = route_map - if bgp_peer.get("default_originate") is not None: - bgp_peer["default_originate"]["route_map"] = bgp_peer["default_originate"].get("route_map", route_map) + bgp_peer_dict["route_map_out"] = route_map + if bgp_peer_dict.get("default_originate") is not None: + bgp_peer_dict["default_originate"].setdefault("route_map", route_map) - bgp_peer.pop("set_ipv4_next_hop", None) - bgp_peer.pop("set_ipv6_next_hop", None) + bgp_peer_dict.pop("set_ipv4_next_hop", None) + bgp_peer_dict.pop("set_ipv6_next_hop", None) - bgp_peer.pop("nodes", None) + bgp_peer_dict.pop("nodes", None) append_if_not_duplicate( list_of_dicts=bgp_vrf.setdefault("neighbors", []), primary_key="ip_address", - new_dict={"ip_address": peer_ip, **bgp_peer}, + new_dict={"ip_address": peer_ip, **bgp_peer_dict}, context="BGP peer defined under VRFs", context_keys=["ip_address"], ) - if ( - get(vrf, "ospf.enabled") is True - and vrf.get("redistribute_ospf") is not False - and self.shared_utils.hostname in get(vrf, "ospf.nodes", default=[self.shared_utils.hostname]) - ): + if vrf.ospf.enabled and vrf.redistribute_ospf and (not vrf.ospf.nodes or self.shared_utils.hostname in vrf.ospf.nodes): bgp_vrf.setdefault("redistribute", {}).update({"ospf": {"enabled": True}}) - if bgp_vrf.get("neighbors"): - platform_bgp_update_wait_install = get(self.shared_utils.platform_settings, "feature_support.bgp_update_wait_install", default=True) is True - if get(self._hostvars, "bgp_update_wait_install", default=True) is True and platform_bgp_update_wait_install: - bgp_vrf.setdefault("updates", {})["wait_install"] = True + if ( + bgp_vrf.get("neighbors") + and self.inputs.bgp_update_wait_install + and self.shared_utils.platform_settings.feature_support.bgp_update_wait_install + ): + bgp_vrf.setdefault("updates", {})["wait_install"] = True bgp_vrf = strip_empties_from_dict(bgp_vrf) @@ -281,9 +273,14 @@ def _router_bgp_vrfs(self: AvdStructuredConfigNetworkServices) -> dict: ) return strip_empties_from_dict(router_bgp) - def _update_router_bgp_vrf_evpn_or_mpls_cfg(self: AvdStructuredConfigNetworkServices, bgp_vrf: dict, vrf: dict, vrf_address_families: list) -> None: + def _update_router_bgp_vrf_evpn_or_mpls_cfg( + self: AvdStructuredConfigNetworkServices, + bgp_vrf: dict, + vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem, + vrf_address_families: list[str], + ) -> None: """In-place update EVPN/MPLS part of structured config for *one* VRF under router_bgp.vrfs.""" - vrf_name = vrf["name"] + vrf_name = vrf.name bgp_vrf["rd"] = self.get_vrf_rd(vrf) vrf_rt = self.get_vrf_rt(vrf) route_targets = {"import": [], "export": []} @@ -299,11 +296,13 @@ def _update_router_bgp_vrf_evpn_or_mpls_cfg(self: AvdStructuredConfigNetworkServ else: target["route_targets"].append(vrf_rt) - for rt in vrf["additional_route_targets"]: - if (target := get_item(route_targets[rt["type"]], "address_family", rt["address_family"])) is None: - route_targets[rt["type"]].append({"address_family": rt["address_family"], "route_targets": [rt["route_target"]]}) + for rt in vrf.additional_route_targets: + if rt.type is None: + continue + if (target := get_item(route_targets[rt.type], "address_family", rt.address_family)) is None: + route_targets[rt.type].append({"address_family": rt.address_family, "route_targets": [rt.route_target]}) else: - target["route_targets"].append(rt["route_target"]) + target["route_targets"].append(rt.route_target) if vrf_name == "default" and self._vrf_default_evpn and self._route_maps_vrf_default: # Special handling of vrf default with evpn. @@ -320,24 +319,30 @@ def _update_router_bgp_vrf_evpn_or_mpls_cfg(self: AvdStructuredConfigNetworkServ return # Not VRF default - bgp_vrf["evpn_multicast"] = get(vrf, "_evpn_l3_multicast_enabled") - if (evpn_multicast_transit_mode := get(vrf, "_evpn_l3_multicast_evpn_peg_transit")) is True: + bgp_vrf["evpn_multicast"] = getattr(vrf, "_evpn_l3_multicast_enabled", None) + if evpn_multicast_transit_mode := getattr(vrf, "_evpn_l3_multicast_evpn_peg_transit", False): bgp_vrf["evpn_multicast_address_family"] = {"ipv4": {"transit": evpn_multicast_transit_mode}} - def _update_router_bgp_vrf_mlag_neighbor_cfg(self: AvdStructuredConfigNetworkServices, bgp_vrf: dict, vrf: dict, tenant: dict, vlan_id: int) -> None: + def _update_router_bgp_vrf_mlag_neighbor_cfg( + self: AvdStructuredConfigNetworkServices, + bgp_vrf: dict, + vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem, + tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem, + vlan_id: int, + ) -> None: """In-place update MLAG neighbor part of structured config for *one* VRF under router_bgp.vrfs.""" if self._exclude_mlag_ibgp_peering_from_redistribute(vrf, tenant): bgp_vrf["redistribute"]["connected"] = {"enabled": True, "route_map": "RM-CONN-2-BGP-VRFS"} interface_name = f"Vlan{vlan_id}" - if self.shared_utils.underlay_rfc5549 and self.shared_utils.overlay_mlag_rfc5549: + if self.inputs.underlay_rfc5549 and self.inputs.overlay_mlag_rfc5549: bgp_vrf.setdefault("neighbor_interfaces", []).append( { "name": interface_name, - "peer_group": self.shared_utils.bgp_peer_groups["mlag_ipv4_underlay_peer"]["name"], + "peer_group": self.inputs.bgp_peer_groups.mlag_ipv4_underlay_peer.name, "remote_as": self.shared_utils.bgp_as, "description": AvdStringFormatter().format( - self.shared_utils.mlag_bgp_peer_description, + self.inputs.mlag_bgp_peer_description, mlag_peer=self.shared_utils.mlag_peer, interface=interface_name, peer_interface=interface_name, @@ -345,26 +350,26 @@ def _update_router_bgp_vrf_mlag_neighbor_cfg(self: AvdStructuredConfigNetworkSer }, ) else: - if (mlag_ibgp_peering_ipv4_pool := vrf.get("mlag_ibgp_peering_ipv4_pool")) is None: + if not vrf.mlag_ibgp_peering_ipv4_pool: ip_address = self.shared_utils.mlag_peer_ibgp_ip elif self.shared_utils.mlag_role == "primary": - ip_address = self.shared_utils.ip_addressing.mlag_ibgp_peering_ip_secondary(mlag_ibgp_peering_ipv4_pool) + ip_address = self.shared_utils.ip_addressing.mlag_ibgp_peering_ip_secondary(vrf.mlag_ibgp_peering_ipv4_pool) else: - ip_address = self.shared_utils.ip_addressing.mlag_ibgp_peering_ip_primary(mlag_ibgp_peering_ipv4_pool) + ip_address = self.shared_utils.ip_addressing.mlag_ibgp_peering_ip_primary(vrf.mlag_ibgp_peering_ipv4_pool) bgp_vrf.setdefault("neighbors", []).append( { "ip_address": ip_address, - "peer_group": self.shared_utils.bgp_peer_groups["mlag_ipv4_underlay_peer"]["name"], + "peer_group": self.inputs.bgp_peer_groups.mlag_ipv4_underlay_peer.name, "description": AvdStringFormatter().format( - self.shared_utils.mlag_bgp_peer_description, + self.inputs.mlag_bgp_peer_description, **strip_empties_from_dict( - {"mlag_peer": self.shared_utils.mlag_peer, "interface": interface_name, "peer_interface": interface_name, "vrf": vrf["name"]} + {"mlag_peer": self.shared_utils.mlag_peer, "interface": interface_name, "peer_interface": interface_name, "vrf": vrf.name} ), ), }, ) - if self.shared_utils.underlay_rfc5549: + if self.inputs.underlay_rfc5549: bgp_vrf.setdefault("address_family_ipv4", {}).setdefault("neighbors", []).append( { "ip_address": ip_address, @@ -377,12 +382,12 @@ def _update_router_bgp_vrf_mlag_neighbor_cfg(self: AvdStructuredConfigNetworkSer def _router_bgp_sorted_vlans_and_svis_lists(self: AvdStructuredConfigNetworkServices) -> dict: tenant_svis_l2vlans_dict = {} for tenant in self.shared_utils.filtered_tenants: - tenant_svis_l2vlans_dict[tenant["name"]] = {} + tenant_svis_l2vlans_dict[tenant.name] = {} # For L2VLANs l2vlans_bundle_dict = {} l2vlans_non_bundle_list = {} - sorted_vlan_list = sorted(tenant["l2vlans"], key=self._get_vlan_aware_bundle_name_tuple_for_l2vlans) + sorted_vlan_list = sorted(tenant.l2vlans, key=self._get_vlan_aware_bundle_name_tuple_for_l2vlans) bundle_groups = itertools_groupby(sorted_vlan_list, self._get_vlan_aware_bundle_name_tuple_for_l2vlans) for vlan_aware_bundle_name_tuple, l2vlans in bundle_groups: bundle_name, is_evpn_vlan_bundle = vlan_aware_bundle_name_tuple @@ -396,24 +401,28 @@ def _router_bgp_sorted_vlans_and_svis_lists(self: AvdStructuredConfigNetworkServ # For SVIs vrf_svis_bundle_dict = {} vrf_svis_non_bundle_dict = {} - for vrf in tenant["vrfs"]: - vrf_svis_non_bundle_dict[vrf["name"]] = [] - vrf_svis_bundle_dict[vrf["name"]] = {} - sorted_svi_list = sorted(vrf["svis"], key=self._get_vlan_aware_bundle_name_tuple_for_svis) + for vrf in tenant.vrfs: + vrf_svis_non_bundle_dict[vrf.name] = [] + vrf_svis_bundle_dict[vrf.name] = {} + sorted_svi_list = sorted(vrf.svis, key=self._get_vlan_aware_bundle_name_tuple_for_svis) bundle_groups_svis = itertools_groupby(sorted_svi_list, self._get_vlan_aware_bundle_name_tuple_for_svis) for vlan_aware_bundle_name_tuple, svis in bundle_groups_svis: bundle_name, is_evpn_vlan_bundle = vlan_aware_bundle_name_tuple svis_list = list(svis) if is_evpn_vlan_bundle: - vrf_svis_bundle_dict[vrf["name"]][bundle_name] = svis_list + vrf_svis_bundle_dict[vrf.name][bundle_name] = svis_list else: - vrf_svis_non_bundle_dict[vrf["name"]] = svis_list + vrf_svis_non_bundle_dict[vrf.name] = svis_list - tenant_svis_l2vlans_dict[tenant["name"]]["svi_bundle"] = vrf_svis_bundle_dict - tenant_svis_l2vlans_dict[tenant["name"]]["svi_non_bundle"] = vrf_svis_non_bundle_dict - tenant_svis_l2vlans_dict[tenant["name"]]["l2vlan_bundle"] = l2vlans_bundle_dict - tenant_svis_l2vlans_dict[tenant["name"]]["l2vlan_non_bundle"] = l2vlans_non_bundle_list + tenant_svis_l2vlans_dict[tenant.name].update( + { + "svi_bundle": vrf_svis_bundle_dict, + "svi_non_bundle": vrf_svis_non_bundle_dict, + "l2vlan_bundle": l2vlans_bundle_dict, + "l2vlan_non_bundle": l2vlans_non_bundle_list, + } + ) return tenant_svis_l2vlans_dict @@ -422,7 +431,7 @@ def _router_bgp_vlans(self: AvdStructuredConfigNetworkServices, tenant_svis_l2vl if not ( self.shared_utils.network_services_l2 and "evpn" in self.shared_utils.overlay_address_families - and not self._evpn_vlan_aware_bundles + and not self.inputs.evpn_vlan_aware_bundles and (self.shared_utils.overlay_vtep or self.shared_utils.overlay_ler) and (self.shared_utils.overlay_evpn) ): @@ -430,10 +439,10 @@ def _router_bgp_vlans(self: AvdStructuredConfigNetworkServices, tenant_svis_l2vl vlans = [] for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: - for svi in tenant_svis_l2vlans_dict[tenant["name"]]["svi_non_bundle"][vrf["name"]]: + for vrf in tenant.vrfs: + for svi in tenant_svis_l2vlans_dict[tenant.name]["svi_non_bundle"][vrf.name]: if (vlan := self._router_bgp_vlans_vlan(svi, tenant, vrf)) is not None: - vlan_id = int(svi["id"]) + vlan_id = svi.id vlan = {"id": vlan_id, **vlan} append_if_not_duplicate( list_of_dicts=vlans, @@ -445,10 +454,14 @@ def _router_bgp_vlans(self: AvdStructuredConfigNetworkServices, tenant_svis_l2vl ) # L2 Vlans per Tenant - for l2vlans in tenant_svis_l2vlans_dict[tenant["name"]]["l2vlan_non_bundle"].values(): + for l2vlans in tenant_svis_l2vlans_dict[tenant.name]["l2vlan_non_bundle"].values(): for l2vlan in l2vlans: - if (vlan := self._router_bgp_vlans_vlan(l2vlan, tenant, vrf={})) is not None: - vlan_id = int(l2vlan["id"]) + if ( + vlan := self._router_bgp_vlans_vlan( + l2vlan, tenant, vrf=EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem() + ) + ) is not None: + vlan_id = l2vlan.id vlan = {"id": vlan_id, **vlan} append_if_not_duplicate( list_of_dicts=vlans, @@ -460,99 +473,107 @@ def _router_bgp_vlans(self: AvdStructuredConfigNetworkServices, tenant_svis_l2vl ) return vlans or None - def _router_bgp_vlans_vlan(self: AvdStructuredConfigNetworkServices, vlan: dict, tenant: dict, vrf: dict) -> dict | None: + def _router_bgp_vlans_vlan( + self: AvdStructuredConfigNetworkServices, + vlan: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem + | EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.L2vlansItem, + tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem, + vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem, + ) -> dict | None: """Return structured config for one given vlan under router_bgp.vlans.""" - if vlan.get("vxlan") is False: + if not vlan.vxlan: return None vlan_rd = self.get_vlan_rd(vlan, tenant) vlan_rt = self.get_vlan_rt(vlan, tenant) bgp_vlan = { - "tenant": vlan["tenant"], + "tenant": vlan._tenant, "rd": vlan_rd, "route_targets": {"both": [vlan_rt]}, "redistribute_routes": ["learned"], - "eos_cli": get(vlan, "bgp.raw_eos_cli"), - "struct_cfg": get(vlan, "bgp.structured_config"), + "eos_cli": vlan.bgp.raw_eos_cli, + "struct_cfg": vlan.bgp.structured_config._as_dict(strip_values=()) or None, } - if ( - self.shared_utils.evpn_gateway_vxlan_l2 - and default(vlan.get("evpn_l2_multi_domain"), vrf.get("evpn_l2_multi_domain"), tenant.get("evpn_l2_multi_domain"), True) is True # noqa: FBT003 + if self.shared_utils.node_config.evpn_gateway.evpn_l2.enabled and default( + vlan.evpn_l2_multi_domain, vrf.evpn_l2_multi_domain, tenant.evpn_l2_multi_domain ): bgp_vlan["rd_evpn_domain"] = {"domain": "remote", "rd": vlan_rd} bgp_vlan["route_targets"]["import_export_evpn_domains"] = [{"domain": "remote", "route_target": vlan_rt}] - vlan_evpn_l2_multicast_enabled = ( - default(get(vlan, "evpn_l2_multicast.enabled"), get(tenant, "evpn_l2_multicast.enabled")) and self.shared_utils.evpn_multicast is True - ) - if vlan_evpn_l2_multicast_enabled is True: - always_redistribute_igmp = default( - get(vlan, "evpn_l2_multicast.always_redistribute_igmp"), - get(tenant, "evpn_l2_multicast.always_redistribute_igmp"), - False, # noqa: FBT003 - ) - # For l2vlans vrf is an empty dict so this will always configure redistribute igmp - if not get(vrf, "_evpn_l3_multicast_enabled") or always_redistribute_igmp: + vlan_evpn_l2_multicast_enabled = default(vlan.evpn_l2_multicast.enabled, tenant.evpn_l2_multicast.enabled) and self.shared_utils.evpn_multicast is True + if vlan_evpn_l2_multicast_enabled: + if isinstance(vlan, EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.L2vlansItem): + # l2vlans will always redistribute IGMP + bgp_vlan["redistribute_routes"].append("igmp") + elif not getattr(vrf, "_evpn_l3_multicast_enabled", False) or bool( + default(vlan.evpn_l2_multicast.always_redistribute_igmp, tenant.evpn_l2_multicast.always_redistribute_igmp) + ): bgp_vlan["redistribute_routes"].append("igmp") # Strip None values from vlan before returning return {key: value for key, value in bgp_vlan.items() if value is not None} - @cached_property - def _evpn_vlan_bundles(self: AvdStructuredConfigNetworkServices) -> list: - return get(self._hostvars, "evpn_vlan_bundles", default=[]) - - @cached_property - def _evpn_vlan_aware_bundles(self: AvdStructuredConfigNetworkServices) -> bool: - return get(self._hostvars, "evpn_vlan_aware_bundles", default=False) - - def _get_vlan_aware_bundle_name_tuple_for_l2vlans(self: AvdStructuredConfigNetworkServices, vlan: dict) -> tuple[str, bool] | None: + def _get_vlan_aware_bundle_name_tuple_for_l2vlans( + self: AvdStructuredConfigNetworkServices, vlan: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.L2vlansItem + ) -> tuple[str, bool] | None: """Return a tuple with string with the vlan-aware-bundle name for one VLAN and a boolean saying if this is a evpn_vlan_bundle.""" - if vlan.get("evpn_vlan_bundle") is not None: - return (str(vlan.get("evpn_vlan_bundle")), True) - return (str(vlan.get("name")), False) + if vlan.evpn_vlan_bundle: + return (vlan.evpn_vlan_bundle, True) + return (vlan.name, False) - def _get_vlan_aware_bundle_name_tuple_for_svis(self: AvdStructuredConfigNetworkServices, vlan: dict) -> tuple[str, bool] | None: + def _get_vlan_aware_bundle_name_tuple_for_svis( + self: AvdStructuredConfigNetworkServices, vlan: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem + ) -> tuple[str, bool] | None: """ Return a tuple with string with the vlan-aware-bundle name for one VLAN and a boolean saying if this is a evpn_vlan_bundle. If no bundle is configured, it will return an empty string as name, since the calling function will then get all svis without bundle grouped under "". """ - if vlan.get("evpn_vlan_bundle") is not None: - return (str(vlan.get("evpn_vlan_bundle")), True) + if vlan.evpn_vlan_bundle: + return (vlan.evpn_vlan_bundle, True) return ("", False) - def _get_evpn_vlan_bundle(self: AvdStructuredConfigNetworkServices, vlan: dict, bundle_name: str) -> dict: + def _get_evpn_vlan_bundle( + self: AvdStructuredConfigNetworkServices, + vlan: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem + | EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.L2vlansItem, + bundle_name: str, + ) -> EosDesigns.EvpnVlanBundlesItem: """Return an evpn_vlan_bundle dict if it exists, else raise an exception.""" - if (evpn_vlan_bundle := get_item(self._evpn_vlan_bundles, "name", bundle_name)) is None: + if bundle_name not in self.inputs.evpn_vlan_bundles: msg = ( "The 'evpn_vlan_bundle' of the svis/l2vlans must be defined in the common 'evpn_vlan_bundles' setting. First occurrence seen for svi/l2vlan" - f" {vlan['id']} in Tenant '{vlan['tenant']}' and evpn_vlan_bundle '{vlan['evpn_vlan_bundle']}'." + f" {vlan.id} in Tenant '{vlan._tenant}' and evpn_vlan_bundle '{vlan.evpn_vlan_bundle}'." ) raise AristaAvdInvalidInputsError(msg) - return evpn_vlan_bundle + return self.inputs.evpn_vlan_bundles[bundle_name] - def _get_svi_l2vlan_bundle(self: AvdStructuredConfigNetworkServices, evpn_vlan_bundle: dict, tenant: dict, vlans: list) -> dict | None: + def _get_svi_l2vlan_bundle( + self: AvdStructuredConfigNetworkServices, + evpn_vlan_bundle: EosDesigns.EvpnVlanBundlesItem, + tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem, + vlans: list, + ) -> dict | None: """Return an bundle config for a svi or l2vlan.""" bundle = self._router_bgp_vlan_aware_bundle( - name=evpn_vlan_bundle["name"], + name=evpn_vlan_bundle.name, vlans=vlans, - rd=self.get_vlan_aware_bundle_rd(id=evpn_vlan_bundle["id"], tenant=tenant, is_vrf=False, rd_override=evpn_vlan_bundle.get("rd_override")), + rd=self.get_vlan_aware_bundle_rd(id=evpn_vlan_bundle.id, tenant=tenant, is_vrf=False, rd_override=evpn_vlan_bundle.rd_override), rt=self.get_vlan_aware_bundle_rt( - id=evpn_vlan_bundle["id"], - vni=evpn_vlan_bundle["id"], + id=evpn_vlan_bundle.id, + vni=evpn_vlan_bundle.id, tenant=tenant, is_vrf=False, - rt_override=evpn_vlan_bundle.get("rt_override"), + rt_override=evpn_vlan_bundle.rt_override, ), - evpn_l2_multi_domain=default(evpn_vlan_bundle.get("evpn_l2_multi_domain"), tenant.get("evpn_l2_multi_domain", True)) is True, + evpn_l2_multi_domain=default(evpn_vlan_bundle.evpn_l2_multi_domain, tenant.evpn_l2_multi_domain), tenant=tenant, ) if bundle is not None: - if (eos_cli := get(evpn_vlan_bundle, "bgp.raw_eos_cli")) is not None: + if (eos_cli := evpn_vlan_bundle.bgp.raw_eos_cli) is not None: bundle["eos_cli"] = eos_cli return bundle @@ -566,8 +587,8 @@ def _router_bgp_vlan_aware_bundles(self: AvdStructuredConfigNetworkServices, ten bundles = [] for tenant in self.shared_utils.filtered_tenants: l2vlan_svi_vlan_aware_bundles = {} - for vrf in tenant["vrfs"]: - for bundle_name, svis in tenant_svis_l2vlans_dict[tenant["name"]]["svi_bundle"][vrf["name"]].items(): + for vrf in tenant.vrfs: + for bundle_name, svis in tenant_svis_l2vlans_dict[tenant.name]["svi_bundle"][vrf.name].items(): # SVIs which have an evpn_vlan_bundle defined if bundle_name in l2vlan_svi_vlan_aware_bundles: l2vlan_svi_vlan_aware_bundles[bundle_name]["l2vlan_svis"].extend(svis) @@ -576,8 +597,8 @@ def _router_bgp_vlan_aware_bundles(self: AvdStructuredConfigNetworkServices, ten evpn_vlan_bundle = self._get_evpn_vlan_bundle(svis[0], bundle_name) l2vlan_svi_vlan_aware_bundles[bundle_name] = {"evpn_vlan_bundle": evpn_vlan_bundle, "l2vlan_svis": svis} - if self._evpn_vlan_aware_bundles: - svis = tenant_svis_l2vlans_dict[tenant["name"]]["svi_non_bundle"][vrf["name"]] + if self.inputs.evpn_vlan_aware_bundles: + svis = tenant_svis_l2vlans_dict[tenant.name]["svi_non_bundle"][vrf.name] # SVIs which don't have an evpn_vlan_bundle defined are included in the VRF vlan-aware-bundle if (bundle := self._router_bgp_vlan_aware_bundles_vrf(vrf, tenant, svis)) is not None: append_if_not_duplicate( @@ -590,7 +611,7 @@ def _router_bgp_vlan_aware_bundles(self: AvdStructuredConfigNetworkServices, ten # L2 Vlans per Tenant # If multiple L2 Vlans share the same evpn_vlan_bundle name, they will be part of the same vlan-aware-bundle else they use the vlan name as bundle - for bundle_name, l2vlans in tenant_svis_l2vlans_dict[tenant["name"]]["l2vlan_bundle"].items(): + for bundle_name, l2vlans in tenant_svis_l2vlans_dict[tenant.name]["l2vlan_bundle"].items(): if bundle_name in l2vlan_svi_vlan_aware_bundles: l2vlan_svi_vlan_aware_bundles[bundle_name]["l2vlan_svis"].extend(l2vlans) else: @@ -598,15 +619,19 @@ def _router_bgp_vlan_aware_bundles(self: AvdStructuredConfigNetworkServices, ten evpn_vlan_bundle = self._get_evpn_vlan_bundle(l2vlans[0], bundle_name) l2vlan_svi_vlan_aware_bundles[bundle_name] = {"evpn_vlan_bundle": evpn_vlan_bundle, "l2vlan_svis": l2vlans} - if self._evpn_vlan_aware_bundles: - for bundle_name, l2vlans in tenant_svis_l2vlans_dict[tenant["name"]]["l2vlan_non_bundle"].items(): + if self.inputs.evpn_vlan_aware_bundles: + for bundle_name, l2vlans in tenant_svis_l2vlans_dict[tenant.name]["l2vlan_non_bundle"].items(): # Without "evpn_vlan_bundle" we fall back to per-vlan behavior - if (bundle := self._router_bgp_vlans_vlan(l2vlans[0], tenant, vrf={})) is None: + if ( + bundle := self._router_bgp_vlans_vlan( + l2vlans[0], tenant, vrf=EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem() + ) + ) is None: # Skip bundle since no vlans were enabled for vxlan. continue # We are reusing the regular bgp vlan function so need to add vlan info - bundle["vlan"] = list_compress([int(l2vlan["id"]) for l2vlan in l2vlans]) + bundle["vlan"] = list_compress([l2vlan.id for l2vlan in l2vlans]) bundle = {"name": bundle_name, **bundle} append_if_not_duplicate( list_of_dicts=bundles, @@ -621,7 +646,7 @@ def _router_bgp_vlan_aware_bundles(self: AvdStructuredConfigNetworkServices, ten # L2VLANs and SVIs which have an evpn_vlan_bundle defined for bundle_dict in l2vlan_svi_vlan_aware_bundles.values(): - evpn_vlan_bundle = bundle_dict["evpn_vlan_bundle"] + evpn_vlan_bundle: EosDesigns.EvpnVlanBundlesItem = bundle_dict["evpn_vlan_bundle"] l2vlans_svis = bundle_dict["l2vlan_svis"] if (bundle := self._get_svi_l2vlan_bundle(evpn_vlan_bundle, tenant, l2vlans_svis)) is None: @@ -641,26 +666,38 @@ def _router_bgp_vlan_aware_bundles(self: AvdStructuredConfigNetworkServices, ten return bundles or None - def _router_bgp_vlan_aware_bundles_vrf(self: AvdStructuredConfigNetworkServices, vrf: dict, tenant: dict, vlans: list[dict]) -> dict | None: + def _router_bgp_vlan_aware_bundles_vrf( + self: AvdStructuredConfigNetworkServices, + vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem, + tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem, + svis: list[EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem], + ) -> dict | None: """Return structured config for one vrf under router_bgp.vlan_aware_bundles.""" return self._router_bgp_vlan_aware_bundle( - name=vrf["name"], - vlans=vlans, + name=vrf.name, + vlans=svis, rd=self.get_vlan_aware_bundle_rd(id=self.shared_utils.get_vrf_id(vrf), tenant=tenant, is_vrf=True), rt=self.get_vlan_aware_bundle_rt(id=self.shared_utils.get_vrf_id(vrf), vni=self.shared_utils.get_vrf_vni(vrf), tenant=tenant, is_vrf=True), - evpn_l2_multi_domain=default(vrf.get("evpn_l2_multi_domain"), tenant.get("evpn_l2_multi_domain", True)) is True, + evpn_l2_multi_domain=default(vrf.evpn_l2_multi_domain, tenant.evpn_l2_multi_domain), tenant=tenant, ) def _router_bgp_vlan_aware_bundle( - self: AvdStructuredConfigNetworkServices, name: str, vlans: list, rd: str, rt: str, evpn_l2_multi_domain: bool, tenant: dict + self: AvdStructuredConfigNetworkServices, + name: str, + vlans: list[EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem] + | list[EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.L2vlansItem], + rd: str, + rt: str, + evpn_l2_multi_domain: bool, + tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem, ) -> dict | None: """ Return structured config for one vlan-aware-bundle. Used for VRFs and bundles defined under "evpn_vlan_bundles" referred by l2vlans and SVIs. """ - vlans = [vlan for vlan in vlans if vlan.get("vxlan") is not False] + vlans = [vlan for vlan in vlans if vlan.vxlan is not False] if not vlans: return None @@ -671,202 +708,17 @@ def _router_bgp_vlan_aware_bundle( "both": [rt], }, "redistribute_routes": ["learned"], - "vlan": list_compress([int(vlan["id"]) for vlan in vlans]), + "vlan": list_compress([vlan.id for vlan in vlans]), } - if self.shared_utils.evpn_gateway_vxlan_l2 and evpn_l2_multi_domain: + if self.shared_utils.node_config.evpn_gateway.evpn_l2.enabled and evpn_l2_multi_domain: bundle["rd_evpn_domain"] = {"domain": "remote", "rd": rd} bundle["route_targets"]["import_export_evpn_domains"] = [{"domain": "remote", "route_target": rt}] - if any(get(vlan, "evpn_l2_multicast.enabled", get(tenant, "evpn_l2_multicast.enabled")) is True for vlan in vlans): + if any(default(vlan.evpn_l2_multicast.enabled, tenant.evpn_l2_multicast.enabled) for vlan in vlans): bundle["redistribute_routes"].append("igmp") return bundle - @cached_property - def _rt_admin_subfield(self: AvdStructuredConfigNetworkServices) -> str | None: - """ - Return a string with the route-target admin subfield unless set to "vrf_id" or "vrf_vni" or "id". - - Returns None if not set, since the calling functions will use - per-vlan numbers by default. - """ - admin_subfield = self.shared_utils.overlay_rt_type["admin_subfield"] - if admin_subfield is None: - return None - - if admin_subfield == "bgp_as": - return self.shared_utils.bgp_as - - if re_fullmatch(r"\d+", str(admin_subfield)): - return admin_subfield - - return None - - def get_vlan_mac_vrf_id(self: AvdStructuredConfigNetworkServices, vlan: dict, tenant: dict) -> int: - mac_vrf_id_base = default(tenant.get("mac_vrf_id_base"), tenant.get("mac_vrf_vni_base")) - if mac_vrf_id_base is None: - msg = ( - "'rt_override' or 'vni_override' or 'mac_vrf_id_base' or 'mac_vrf_vni_base' must be set. " - f"Unable to set EVPN RD/RT for vlan {vlan['id']} in Tenant '{vlan['tenant']}'" - ) - raise AristaAvdInvalidInputsError(msg) - return mac_vrf_id_base + int(vlan["id"]) - - def get_vlan_mac_vrf_vni(self: AvdStructuredConfigNetworkServices, vlan: dict, tenant: dict) -> int: - mac_vrf_vni_base = default(tenant.get("mac_vrf_vni_base"), tenant.get("mac_vrf_id_base")) - if mac_vrf_vni_base is None: - msg = ( - "'rt_override' or 'vni_override' or 'mac_vrf_id_base' or 'mac_vrf_vni_base' must be set. " - f"Unable to set EVPN RD/RT for vlan {vlan['id']} in Tenant '{vlan['tenant']}'" - ) - raise AristaAvdInvalidInputsError(msg) - return mac_vrf_vni_base + int(vlan["id"]) - - def get_vlan_rd(self: AvdStructuredConfigNetworkServices, vlan: dict, tenant: dict) -> str: - """Return a string with the route-destinguisher for one VLAN.""" - rd_override = default(vlan.get("rd_override"), vlan.get("rt_override"), vlan.get("vni_override")) - - if ":" in str(rd_override): - return rd_override - - if rd_override is not None: - assigned_number_subfield = rd_override - elif self.shared_utils.overlay_rd_type["vlan_assigned_number_subfield"] == "mac_vrf_vni": - assigned_number_subfield = self.get_vlan_mac_vrf_vni(vlan, tenant) - elif self.shared_utils.overlay_rd_type["vlan_assigned_number_subfield"] == "vlan_id": - assigned_number_subfield = vlan["id"] - else: - assigned_number_subfield = self.get_vlan_mac_vrf_id(vlan, tenant) - - return f"{self.shared_utils.overlay_rd_type_admin_subfield}:{assigned_number_subfield}" - - def get_vlan_rt(self: AvdStructuredConfigNetworkServices, vlan: dict, tenant: dict) -> str: - """Return a string with the route-target for one VLAN.""" - rt_override = default(vlan.get("rt_override"), vlan.get("vni_override")) - - if ":" in str(rt_override): - return rt_override - - if self._rt_admin_subfield is not None: - admin_subfield = self._rt_admin_subfield - elif rt_override is not None: - admin_subfield = rt_override - elif self.shared_utils.overlay_rt_type["admin_subfield"] == "vrf_vni": - admin_subfield = self.get_vlan_mac_vrf_vni(vlan, tenant) - elif self.shared_utils.overlay_rt_type["admin_subfield"] == "id": - admin_subfield = vlan["id"] - else: - admin_subfield = self.get_vlan_mac_vrf_id(vlan, tenant) - - if rt_override is not None: - assigned_number_subfield = rt_override - elif self.shared_utils.overlay_rt_type["vlan_assigned_number_subfield"] == "mac_vrf_vni": - assigned_number_subfield = self.get_vlan_mac_vrf_vni(vlan, tenant) - elif self.shared_utils.overlay_rt_type["vlan_assigned_number_subfield"] == "vlan_id": - assigned_number_subfield = vlan["id"] - else: - assigned_number_subfield = self.get_vlan_mac_vrf_id(vlan, tenant) - - return f"{admin_subfield}:{assigned_number_subfield}" - - @cached_property - def _vrf_rt_admin_subfield(self: AvdStructuredConfigNetworkServices) -> str | None: - """ - Return a string with the VRF route-target admin subfield unless set to "vrf_id" or "vrf_vni" or "id". - - Returns None if not set, since the calling functions will use - per-vrf numbers by default. - """ - admin_subfield = self.shared_utils.overlay_rt_type["vrf_admin_subfield"] - if admin_subfield is None: - return None - - if admin_subfield == "bgp_as": - return self.shared_utils.bgp_as - - if re_fullmatch(r"\d+", str(admin_subfield)): - return admin_subfield - - return None - - def get_vrf_rd(self: AvdStructuredConfigNetworkServices, vrf: dict) -> str: - """Return a string with the route-destinguisher for one VRF.""" - rd_override = default(vrf.get("rd_override")) - - if ":" in str(rd_override): - return rd_override - - if rd_override is not None: - return f"{self.shared_utils.overlay_rd_type_vrf_admin_subfield}:{rd_override}" - - return f"{self.shared_utils.overlay_rd_type_vrf_admin_subfield}:{self.shared_utils.get_vrf_id(vrf)}" - - def get_vrf_rt(self: AvdStructuredConfigNetworkServices, vrf: dict) -> str: - """Return a string with the route-target for one VRF.""" - rt_override = default(vrf.get("rt_override")) - - if ":" in str(rt_override): - return rt_override - - if self._vrf_rt_admin_subfield is not None: - admin_subfield = self._vrf_rt_admin_subfield - elif self.shared_utils.overlay_rt_type["vrf_admin_subfield"] == "vrf_vni": - admin_subfield = self.shared_utils.get_vrf_vni(vrf) - else: - # Both for 'id' and 'vrf_id' options. - admin_subfield = self.shared_utils.get_vrf_id(vrf) - - if rt_override is not None: - return f"{admin_subfield}:{rt_override}" - - return f"{admin_subfield}:{self.shared_utils.get_vrf_id(vrf)}" - - def get_vlan_aware_bundle_rd( - self: AvdStructuredConfigNetworkServices, - id: int, # noqa: A002 - tenant: dict, - is_vrf: bool, - rd_override: str | None = None, - ) -> str: - """Return a string with the route-destinguisher for one VLAN Aware Bundle.""" - admin_subfield = self.shared_utils.overlay_rd_type_vrf_admin_subfield if is_vrf else self.shared_utils.overlay_rd_type_admin_subfield - - if rd_override is not None: - if ":" in str(rd_override): - return rd_override - - return f"{admin_subfield}:{rd_override}" - - bundle_number = id + int(get(tenant, "vlan_aware_bundle_number_base", default=0)) - return f"{admin_subfield}:{bundle_number}" - - def get_vlan_aware_bundle_rt( - self: AvdStructuredConfigNetworkServices, - id: int, # noqa: A002 - vni: int, - tenant: dict, - is_vrf: bool, - rt_override: str | None = None, - ) -> str: - """Return a string with the route-target for one VLAN Aware Bundle.""" - if rt_override is not None and ":" in str(rt_override): - return rt_override - - bundle_number = id + int(get(tenant, "vlan_aware_bundle_number_base", default=0)) - - if is_vrf and self._vrf_rt_admin_subfield is not None: - admin_subfield = self._vrf_rt_admin_subfield - elif is_vrf and self.shared_utils.overlay_rt_type["vrf_admin_subfield"] == "vrf_vni": - admin_subfield = vni - else: - # Both for 'id' and 'vrf_id' options. - admin_subfield = bundle_number - - if rt_override is not None: - return f"{admin_subfield}:{rt_override}" - - return f"{admin_subfield}:{bundle_number}" - @cached_property def _router_bgp_redistribute_routes(self: AvdStructuredConfigNetworkServices) -> dict | None: """ @@ -897,53 +749,45 @@ def _router_bgp_vpws(self: AvdStructuredConfigNetworkServices) -> list[dict] | N vpws = [] for tenant in self.shared_utils.filtered_tenants: - if "point_to_point_services" not in tenant: - continue - - if get(tenant, "pseudowire_rt_base") is None: + if not tenant.point_to_point_services or tenant.pseudowire_rt_base is None: continue pseudowires = [] - for point_to_point_service in natural_sort(tenant["point_to_point_services"], "name"): - if subifs := point_to_point_service.get("subinterfaces", []): - subifs = [subif for subif in subifs if subif.get("number") is not None] - - endpoints = point_to_point_service.get("endpoints", []) + for point_to_point_service in tenant.point_to_point_services._natural_sorted(): + endpoints = point_to_point_service.endpoints for local_index, endpoint in enumerate(endpoints): - if not (self.shared_utils.hostname in endpoint.get("nodes", []) and endpoint.get("interfaces") is not None): + if self.shared_utils.hostname not in endpoint.nodes or not endpoint.interfaces: continue # Endpoints can only have two entries with index 0 and 1. # So the remote must be the other index. remote_endpoint = endpoints[(local_index + 1) % 2] - if subifs: - for subif in subifs: - subif_number = int(subif["number"]) - pseudowires.append( - { - "name": f"{point_to_point_service['name']}_{subif_number}", - "id_local": int(endpoint["id"]) + subif_number, - "id_remote": int(remote_endpoint["id"]) + subif_number, - }, - ) + if point_to_point_service.subinterfaces: + pseudowires.extend( + { + "name": f"{point_to_point_service.name}_{subif.number}", + "id_local": endpoint.id + subif.number, + "id_remote": remote_endpoint.id + subif.number, + } + for subif in point_to_point_service.subinterfaces + ) else: pseudowires.append( { - "name": f"{point_to_point_service['name']}", - "id_local": int(endpoint["id"]), - "id_remote": int(remote_endpoint["id"]), + "name": point_to_point_service.name, + "id_local": endpoint.id, + "id_remote": remote_endpoint.id, }, ) if pseudowires: - rt_base = get(tenant, "pseudowire_rt_base", required=True, custom_error_msg=f"'pseudowire_rt_base' under Tenant '{tenant['name']} is required.") - rd = f"{self.shared_utils.overlay_rd_type_admin_subfield}:{rt_base}" - rt = f"{self._rt_admin_subfield or rt_base}:{rt_base}" + rd = f"{self.shared_utils.overlay_rd_type_admin_subfield}:{tenant.pseudowire_rt_base}" + rt = f"{self._rt_admin_subfield or tenant.pseudowire_rt_base}:{tenant.pseudowire_rt_base}" vpws.append( { - "name": tenant["name"], + "name": tenant.name, "rd": rd, "route_targets": {"import_export": rt}, "pseudowires": pseudowires, @@ -961,21 +805,21 @@ def _router_bgp_mlag_peer_group(self: AvdStructuredConfigNetworkServices) -> dic TODO: Partially duplicated from mlag. Should be moved to a common class """ - peer_group_name = self.shared_utils.bgp_peer_groups["mlag_ipv4_underlay_peer"]["name"] + peer_group_name = self.inputs.bgp_peer_groups.mlag_ipv4_underlay_peer.name router_bgp = {} peer_group = { "name": peer_group_name, "type": "ipv4", "remote_as": self.shared_utils.bgp_as, "next_hop_self": True, - "description": AvdStringFormatter().format(self.shared_utils.mlag_bgp_peer_group_description, mlag_peer=self.shared_utils.mlag_peer), - "password": self.shared_utils.bgp_peer_groups["mlag_ipv4_underlay_peer"]["password"], + "description": AvdStringFormatter().format(self.inputs.mlag_bgp_peer_group_description, mlag_peer=self.shared_utils.mlag_peer), + "password": self.inputs.bgp_peer_groups.mlag_ipv4_underlay_peer.password, "maximum_routes": 12000, "send_community": "all", - "struct_cfg": self.shared_utils.bgp_peer_groups["mlag_ipv4_underlay_peer"]["structured_config"], + "struct_cfg": self.inputs.bgp_peer_groups.mlag_ipv4_underlay_peer.structured_config._as_dict(strip_values=()) or None, } - if self.shared_utils.mlag_ibgp_origin_incomplete is True: + if self.shared_utils.node_config.mlag_ibgp_origin_incomplete: peer_group["route_map_in"] = "RM-MLAG-PEER-IN" router_bgp["peer_groups"] = [peer_group] @@ -991,7 +835,7 @@ def _router_bgp_mlag_peer_group(self: AvdStructuredConfigNetworkServices) -> dic } address_family_ipv4_peer_group = {"name": peer_group_name, "activate": True} - if self.shared_utils.underlay_rfc5549: + if self.inputs.underlay_rfc5549: address_family_ipv4_peer_group["next_hop"] = {"address_family_ipv6": {"enabled": True, "originate": True}} router_bgp["address_family_ipv4"] = {"peer_groups": [address_family_ipv4_peer_group]} diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/router_internet_exit.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/router_internet_exit.py index edf1959178c..a5b235f429b 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/router_internet_exit.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/router_internet_exit.py @@ -7,8 +7,6 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import get - from .utils import UtilsMixin if TYPE_CHECKING: @@ -29,28 +27,28 @@ def router_internet_exit(self: AvdStructuredConfigNetworkServices) -> dict | Non Only used for CV Pathfinder edge routers today """ - if not self._filtered_internet_exit_policies: + if not self._filtered_internet_exit_policies_and_connections: return None router_internet_exit = {} exit_groups_dict = defaultdict(lambda: {"local_connections": []}) policies = [] - for policy in self._filtered_internet_exit_policies: + for policy, connections in self._filtered_internet_exit_policies_and_connections: policy_exit_groups = [] # TODO: Today we use the order of the connection list to order the exit-groups inside the policy. # This works for zscaler but later we may need to use some sorting intelligence as order matters. - for connection in policy.get("connections", []): + for connection in connections: exit_group_name = connection["exit_group"] exit_groups_dict[exit_group_name]["local_connections"].append({"name": connection["name"]}) # Recording the exit_group in the policy if exit_group_name not in policy_exit_groups: policy_exit_groups.append(exit_group_name) - if get(policy, "fallback_to_system_default", default=True): + if policy.fallback_to_system_default: policy_exit_groups.append("system-default-exit-group") - policies.append({"name": policy["name"], "exit_groups": [{"name": exit_group_name} for exit_group_name in policy_exit_groups]}) + policies.append({"name": policy.name, "exit_groups": [{"name": exit_group_name} for exit_group_name in policy_exit_groups]}) if exit_groups_dict: router_internet_exit["exit_groups"] = [ diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/router_multicast.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/router_multicast.py index a674af68839..1ee38a8e710 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/router_multicast.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/router_multicast.py @@ -6,7 +6,7 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import append_if_not_duplicate, get +from pyavd._utils import append_if_not_duplicate from .utils import UtilsMixin @@ -33,9 +33,9 @@ def router_multicast(self: AvdStructuredConfigNetworkServices) -> dict | None: vrfs = [] for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: - if get(vrf, "_evpn_l3_multicast_enabled"): - vrf_config = {"name": vrf["name"], "ipv4": {"routing": True}} + for vrf in tenant.vrfs: + if getattr(vrf, "_evpn_l3_multicast_enabled", False): + vrf_config = {"name": vrf.name, "ipv4": {"routing": True}} append_if_not_duplicate( list_of_dicts=vrfs, primary_key="name", diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/router_ospf.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/router_ospf.py index 729129e6291..bd08917262b 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/router_ospf.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/router_ospf.py @@ -7,7 +7,7 @@ from typing import TYPE_CHECKING from pyavd._errors import AristaAvdInvalidInputsError -from pyavd._utils import append_if_not_duplicate, default, get +from pyavd._utils import append_if_not_duplicate, default from .utils import UtilsMixin @@ -35,56 +35,52 @@ def router_ospf(self: AvdStructuredConfigNetworkServices) -> dict | None: ospf_processes = [] for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: - if get(vrf, "ospf.enabled") is not True: + for vrf in tenant.vrfs: + if not vrf.ospf.enabled: continue - if self.shared_utils.hostname not in get(vrf, "ospf.nodes", default=[self.shared_utils.hostname]): + if vrf.ospf.nodes and self.shared_utils.hostname not in vrf.ospf.nodes: continue ospf_interfaces = [] - for l3_interface in vrf["l3_interfaces"]: - if get(l3_interface, "ospf.enabled") is True: - for node_index, node in enumerate(l3_interface["nodes"]): + for l3_interface in vrf.l3_interfaces: + if l3_interface.ospf.enabled: + for node_index, node in enumerate(l3_interface.nodes): if node != self.shared_utils.hostname: continue - ospf_interfaces.append(l3_interface["interfaces"][node_index]) + ospf_interfaces.append(l3_interface.interfaces[node_index]) - for svi in vrf["svis"]: - if get(svi, "ospf.enabled") is True: - interface_name = f"Vlan{svi['id']}" + for svi in vrf.svis: + if svi.ospf.enabled: + interface_name = f"Vlan{svi.id}" ospf_interfaces.append(interface_name) - process_id = default(get(vrf, "ospf.process_id"), vrf.get("vrf_id")) + process_id = default(vrf.ospf.process_id, vrf.vrf_id) if not process_id: - msg = f"'ospf.process_id' or 'vrf_id' under vrf '{vrf['name']}" + msg = f"Missing or invalid 'ospf.process_id' or 'vrf_id' under vrf '{vrf.name}" raise AristaAvdInvalidInputsError(msg) process = { "id": process_id, - "vrf": vrf["name"] if vrf["name"] != "default" else None, + "vrf": vrf.name if vrf.name != "default" else None, "passive_interface_default": True, + "router_id": default(vrf.ospf.router_id, self.shared_utils.router_id if not self.inputs.use_router_general_for_router_id else None), "no_passive_interfaces": ospf_interfaces, - "bfd_enable": get(vrf, "ospf.bfd"), - "max_lsa": get(vrf, "ospf.max_lsa"), + "bfd_enable": vrf.ospf.bfd or None, # Historic behavior is to only output if True. + "max_lsa": vrf.ospf.max_lsa, } - if ospf_router_id := get(vrf, "ospf.router_id"): - process["router_id"] = ospf_router_id - elif not self.shared_utils.use_router_general_for_router_id: - process["router_id"] = self.shared_utils.router_id - process_redistribute = {} - if get(vrf, "ospf.redistribute_bgp.enabled", default=True) is True: + if vrf.ospf.redistribute_bgp.enabled: process_redistribute["bgp"] = {"enabled": True} - if (route_map := get(vrf, "ospf.redistribute_bgp.route_map")) is not None: + if route_map := vrf.ospf.redistribute_bgp.route_map: process_redistribute["bgp"]["route_map"] = route_map - if get(vrf, "ospf.redistribute_connected.enabled", default=False) is True: + if vrf.ospf.redistribute_connected.enabled: process_redistribute["connected"] = {"enabled": True} - if (route_map := get(vrf, "ospf.redistribute_connected.route_map")) is not None: + if route_map := vrf.ospf.redistribute_connected.route_map: process_redistribute["connected"]["route_map"] = route_map process["redistribute"] = process_redistribute or None @@ -97,13 +93,13 @@ def router_ospf(self: AvdStructuredConfigNetworkServices) -> dict | None: primary_key="id", new_dict=process, context="OSPF Processes defined under network services", - context_keys="id", + context_keys=["id"], ) # If we have static_routes in default VRF and not EPVN, and underlay is OSPF # Then add redistribute static to the underlay OSPF process. if self._vrf_default_ipv4_static_routes["redistribute_in_underlay"] and self.shared_utils.underlay_routing_protocol in ["ospf", "ospf-ldp"]: - ospf_processes.append({"id": int(self.shared_utils.underlay_ospf_process_id), "redistribute": {"static": {"enabled": True}}}) + ospf_processes.append({"id": self.inputs.underlay_ospf_process_id, "redistribute": {"static": {"enabled": True}}}) if ospf_processes: return {"process_ids": ospf_processes} diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/router_path_selection.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/router_path_selection.py index 7c08ecdfaea..a62fc424cde 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/router_path_selection.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/router_path_selection.py @@ -33,8 +33,10 @@ def router_path_selection(self: AvdStructuredConfigNetworkServices) -> dict | No # When running CV Pathfinder, only load balance policies are configured # for AutoVPN, need also vrfs and policies. - if self.shared_utils.wan_mode == "autovpn": - vrfs = [{"name": vrf["name"], "path_selection_policy": vrf["policy"]} for vrf in self._filtered_wan_vrfs] + if self.inputs.wan_mode == "autovpn": + vrfs = [ + {"name": vrf.name, "path_selection_policy": f"{vrf.policy}-WITH-CP" if vrf.name == "default" else vrf.policy} for vrf in self._filtered_wan_vrfs + ] router_path_selection.update( { diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/router_pim_sparse_mode.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/router_pim_sparse_mode.py index a86c850fa4d..82492e43d41 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/router_pim_sparse_mode.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/router_pim_sparse_mode.py @@ -6,7 +6,7 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import append_if_not_duplicate, get +from pyavd._utils import append_if_not_duplicate from .utils import UtilsMixin @@ -33,10 +33,10 @@ def router_pim_sparse_mode(self: AvdStructuredConfigNetworkServices) -> dict | N vrfs = [] for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: - if vrf_rps := get(vrf, "_pim_rp_addresses"): + for vrf in tenant.vrfs: + if vrf_rps := getattr(vrf, "_pim_rp_addresses", None): vrf_config = { - "name": vrf["name"], + "name": vrf.name, "ipv4": { "rp_addresses": vrf_rps, }, diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/router_service_insertion.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/router_service_insertion.py index 004eecd07d2..1f3cef2f2c4 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/router_service_insertion.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/router_service_insertion.py @@ -26,14 +26,13 @@ def router_service_insertion(self: AvdStructuredConfigNetworkServices) -> dict | Only used for CV Pathfinder edge routers today """ - if not self._filtered_internet_exit_policies: + if not self._filtered_internet_exit_policies_and_connections: return None - router_service_insertion = {} - connections = [] + service_connections = [] - for policy in self._filtered_internet_exit_policies: - for connection in policy.get("connections", []): + for _policy, connections in self._filtered_internet_exit_policies_and_connections: + for connection in connections: service_connection = { "name": connection["name"], "monitor_connectivity_host": connection["monitor_name"], @@ -49,12 +48,9 @@ def router_service_insertion(self: AvdStructuredConfigNetworkServices) -> dict | "next_hop": connection["next_hop"], } - connections.append(service_connection) - if connections: - router_service_insertion["enabled"] = True - router_service_insertion["connections"] = connections + service_connections.append(service_connection) - if router_service_insertion: - return router_service_insertion + if service_connections: + return {"enabled": True, "connections": service_connections} return None diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/spanning_tree.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/spanning_tree.py index 74c08520ab5..f199f3fb93e 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/spanning_tree.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/spanning_tree.py @@ -6,7 +6,6 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import get from pyavd.j2filters import list_compress from .utils import UtilsMixin @@ -28,26 +27,26 @@ def spanning_tree(self: AvdStructuredConfigNetworkServices) -> dict | None: if not self.shared_utils.network_services_l2: return None - spanning_tree_mode = get(self.shared_utils.switch_data_combined, "spanning_tree_mode") + spanning_tree_mode = self.shared_utils.node_config.spanning_tree_mode if spanning_tree_mode != "rapid-pvst": return None - default_priority = int(get(self.shared_utils.switch_data_combined, "spanning_tree_priority", default=32768)) + default_priority = self.shared_utils.node_config.spanning_tree_priority vlan_stp_priorities = {} non_default_vlans = set() for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: - for svi in vrf["svis"]: - if (priority := get(svi, "spanning_tree_priority")) is None: + for vrf in tenant.vrfs: + for svi in vrf.svis: + if (priority := svi.spanning_tree_priority) is None: continue - vlan_stp_priorities.setdefault(priority, set()).add(svi["id"]) - non_default_vlans.add(svi["id"]) - for l2vlan in tenant["l2vlans"]: - if (priority := get(l2vlan, "spanning_tree_priority")) is None: + vlan_stp_priorities.setdefault(priority, set()).add(svi.id) + non_default_vlans.add(svi.id) + for l2vlan in tenant.l2vlans: + if (priority := l2vlan.spanning_tree_priority) is None: continue - vlan_stp_priorities.setdefault(priority, set()).add(l2vlan["id"]) - non_default_vlans.add(l2vlan["id"]) + vlan_stp_priorities.setdefault(priority, set()).add(l2vlan.id) + non_default_vlans.add(l2vlan.id) if not non_default_vlans: # Quick return with only default diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/standard_access_lists.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/standard_access_lists.py index 6c2932e766b..69dbb27285f 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/standard_access_lists.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/standard_access_lists.py @@ -6,7 +6,7 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import append_if_not_duplicate, default, get +from pyavd._utils import append_if_not_duplicate from .utils import UtilsMixin @@ -33,30 +33,29 @@ def standard_access_lists(self: AvdStructuredConfigNetworkServices) -> list | No standard_access_lists = [] for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: - for rp_entry in default(get(vrf, "pim_rp_addresses"), get(tenant, "pim_rp_addresses"), []): - if self.shared_utils.hostname in get(rp_entry, "nodes", default=[self.shared_utils.hostname]): - if rp_entry.get("groups") is None or rp_entry.get("access_list_name") is None: - continue - - standard_access_list = { - "name": rp_entry["access_list_name"], - "sequence_numbers": [ - { - "sequence": (index + 1) * 10, - "action": f"permit {group}", - } - for index, group in enumerate(rp_entry["groups"]) - ], - } - - append_if_not_duplicate( - list_of_dicts=standard_access_lists, - primary_key="name", - new_dict=standard_access_list, - context="PIM RP Address ACL for VRFs", - context_keys=["name"], - ) + for vrf in tenant.vrfs: + for rp_entry in vrf.pim_rp_addresses or tenant.pim_rp_addresses: + if (rp_entry.nodes and self.shared_utils.hostname not in rp_entry.nodes) or not rp_entry.groups or not rp_entry.access_list_name: + continue + + standard_access_list = { + "name": rp_entry.access_list_name, + "sequence_numbers": [ + { + "sequence": (index) * 10, + "action": f"permit {group}", + } + for index, group in enumerate(rp_entry.groups, 1) + ], + } + + append_if_not_duplicate( + list_of_dicts=standard_access_lists, + primary_key="name", + new_dict=standard_access_list, + context="PIM RP Address ACL for VRFs", + context_keys=["name"], + ) if standard_access_lists: return standard_access_lists diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/static_routes.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/static_routes.py index 75e430f233f..ff8d6eda18a 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/static_routes.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/static_routes.py @@ -34,39 +34,40 @@ def static_routes(self: AvdStructuredConfigNetworkServices) -> list[dict] | None static_routes = [] for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: + for vrf in tenant.vrfs: # Static routes are already filtered inside filtered_tenants - for static_route in vrf["static_routes"]: - static_route["vrf"] = vrf["name"] - static_route.pop("nodes", None) + for static_route in vrf.static_routes: + static_route_dict = static_route._as_dict() + static_route_dict["vrf"] = vrf.name + static_route_dict.pop("nodes", None) # Ignore duplicate items in case of duplicate VRF definitions across multiple tenants. - if static_route not in static_routes: - static_routes.append(static_route) + if static_route_dict not in static_routes: + static_routes.append(static_route_dict) - for svi in vrf["svis"]: - if "ip_virtual_router_addresses" not in svi or "ip_address" not in svi: + for svi in vrf.svis: + if not svi.ip_virtual_router_addresses or not svi.ip_address: # Skip svi if VARP is not set or if there is no unique ip_address continue - for virtual_router_address in svi["ip_virtual_router_addresses"]: + for virtual_router_address in svi.ip_virtual_router_addresses: if "/" not in virtual_router_address: # Only create static routes for VARP entries with masks continue static_route = { "destination_address_prefix": str(ipaddress.ip_network(virtual_router_address, strict=False)), - "vrf": vrf["name"], + "vrf": vrf.name, "name": "VARP", - "interface": f"Vlan{svi['id']}", + "interface": f"Vlan{svi.id}", } # Ignore duplicate items in case of duplicate VRF definitions across multiple tenants. if static_route not in static_routes: static_routes.append(static_route) - for internet_exit_policy in self._filtered_internet_exit_policies: - for connection in internet_exit_policy.get("connections", []): + for _internet_exit_policy, connections in self._filtered_internet_exit_policies_and_connections: + for connection in connections: if connection["type"] == "tunnel": static_route = { "destination_address_prefix": f"{connection['tunnel_destination_ip']}/32", diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/struct_cfgs.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/struct_cfgs.py index 2976a5711d5..4b34c21ceb0 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/struct_cfgs.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/struct_cfgs.py @@ -29,10 +29,10 @@ def struct_cfgs(self: AvdStructuredConfigNetworkServices) -> list | None: vrf_struct_cfgs = [] for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: - if (structured_config := vrf.get("structured_config")) is not None: + for vrf in tenant.vrfs: + if vrf.structured_config: # Inserting VRF into structured_config to perform duplication checks - vrf_struct_cfg = {"vrf": vrf["name"], "struct_cfg": structured_config} + vrf_struct_cfg = {"vrf": vrf.name, "struct_cfg": vrf.structured_config._as_dict(strip_values=())} append_if_not_duplicate( list_of_dicts=vrf_struct_cfgs, primary_key="vrf", diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/tunnel_interfaces.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/tunnel_interfaces.py index e1121b91773..0a8cab363d7 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/tunnel_interfaces.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/tunnel_interfaces.py @@ -28,13 +28,13 @@ def tunnel_interfaces(self: AvdStructuredConfigNetworkServices) -> list | None: Only used for CV Pathfinder edge routers today """ - if not self._filtered_internet_exit_policies: + if not self._filtered_internet_exit_policies_and_connections: return None tunnel_interfaces = [] - for internet_exit_policy in self._filtered_internet_exit_policies: - for connection in internet_exit_policy.get("connections", []): + for internet_exit_policy, connections in self._filtered_internet_exit_policies_and_connections: + for connection in connections: if connection["type"] == "tunnel": tunnel_interface = { "name": f"Tunnel{connection['tunnel_id']}", @@ -47,8 +47,8 @@ def tunnel_interfaces(self: AvdStructuredConfigNetworkServices) -> list | None: "ipsec_profile": connection["ipsec_profile"], } - if internet_exit_policy["type"] == "zscaler": - tunnel_interface["nat_profile"] = self.get_internet_exit_nat_profile_name(internet_exit_policy["type"]) + if internet_exit_policy.type == "zscaler": + tunnel_interface["nat_profile"] = self.get_internet_exit_nat_profile_name(internet_exit_policy.type) append_if_not_duplicate( list_of_dicts=tunnel_interfaces, diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/utils.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/utils.py index 088287e6c0f..7fe4e8cd96a 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/utils.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/utils.py @@ -5,16 +5,19 @@ import ipaddress from functools import cached_property +from re import fullmatch as re_fullmatch from typing import TYPE_CHECKING from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError -from pyavd._utils import default, get, get_item +from pyavd._utils import default, get from pyavd.j2filters import natural_sort from .utils_wan import UtilsWanMixin from .utils_zscaler import UtilsZscalerMixin if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + from . import AvdStructuredConfigNetworkServices @@ -25,18 +28,6 @@ class UtilsMixin(UtilsWanMixin, UtilsZscalerMixin): Class should only be used as Mixin to a AvdStructuredConfig class. """ - @cached_property - def _trunk_groups_mlag_name(self: AvdStructuredConfigNetworkServices) -> str: - return get(self.shared_utils.trunk_groups, "mlag.name", required=True) - - @cached_property - def _trunk_groups_mlag_l3_name(self: AvdStructuredConfigNetworkServices) -> str: - return get(self.shared_utils.trunk_groups, "mlag_l3.name", required=True) - - @cached_property - def _trunk_groups_uplink_name(self: AvdStructuredConfigNetworkServices) -> str: - return get(self.shared_utils.trunk_groups, "uplink.name", required=True) - @cached_property def _local_endpoint_trunk_groups(self: AvdStructuredConfigNetworkServices) -> set: return set(get(self._hostvars, "switch.local_endpoint_trunk_groups", default=[])) @@ -48,11 +39,11 @@ def _vrf_default_evpn(self: AvdStructuredConfigNetworkServices) -> bool: return False for tenant in self.shared_utils.filtered_tenants: - if (vrf_default := get_item(tenant["vrfs"], "name", "default")) is None: + if "default" not in tenant.vrfs: continue - if "evpn" in vrf_default.get("address_families", ["evpn"]): - if self.shared_utils.underlay_filter_peer_as: + if "evpn" in tenant.vrfs["default"].address_families: + if self.inputs.underlay_filter_peer_as: msg = "'underlay_filter_peer_as' cannot be used while there are EVPN services in the default VRF." raise AristaAvdError(msg) return True @@ -64,11 +55,11 @@ def _vrf_default_ipv4_subnets(self: AvdStructuredConfigNetworkServices) -> list[ """Return list of ipv4 subnets in VRF "default".""" subnets = [] for tenant in self.shared_utils.filtered_tenants: - if (vrf_default := get_item(tenant["vrfs"], "name", "default")) is None: + if "default" not in tenant.vrfs: continue - for svi in vrf_default["svis"]: - ip_address = default(svi.get("ip_address"), svi.get("ip_address_virtual")) + for svi in tenant.vrfs["default"].svis: + ip_address = default(svi.ip_address, svi.ip_address_virtual) if ip_address is None: continue @@ -100,16 +91,16 @@ def _vrf_default_ipv4_static_routes(self: AvdStructuredConfigNetworkServices) -> vrf_default_ipv4_static_routes = set() vrf_default_redistribute_static = True for tenant in self.shared_utils.filtered_tenants: - if (vrf_default := get_item(tenant["vrfs"], "name", "default")) is None: + if "default" not in tenant.vrfs: continue - if (static_routes := vrf_default.get("static_routes")) is None: + if not (static_routes := tenant.vrfs["default"].static_routes): continue for static_route in static_routes: - vrf_default_ipv4_static_routes.add(static_route["destination_address_prefix"]) + vrf_default_ipv4_static_routes.add(static_route.destination_address_prefix) - vrf_default_redistribute_static = vrf_default.get("redistribute_static", vrf_default_redistribute_static) + vrf_default_redistribute_static = default(tenant.vrfs["default"].redistribute_static, vrf_default_redistribute_static) if self.shared_utils.overlay_evpn and self.shared_utils.overlay_vtep: # This is an EVPN VTEP @@ -126,7 +117,11 @@ def _vrf_default_ipv4_static_routes(self: AvdStructuredConfigNetworkServices) -> "redistribute_in_overlay": redistribute_in_overlay, } - def _mlag_ibgp_peering_enabled(self: AvdStructuredConfigNetworkServices, vrf: dict, tenant: dict) -> bool: + def _mlag_ibgp_peering_enabled( + self: AvdStructuredConfigNetworkServices, + vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem, + tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem, + ) -> bool: """ Returns True if mlag ibgp_peering is enabled. @@ -137,10 +132,14 @@ def _mlag_ibgp_peering_enabled(self: AvdStructuredConfigNetworkServices, vrf: di if not self.shared_utils.mlag_l3 or not self.shared_utils.network_services_l3: return False - mlag_ibgp_peering: bool = default(vrf.get("enable_mlag_ibgp_peering_vrfs"), tenant.get("enable_mlag_ibgp_peering_vrfs"), True) # noqa: FBT003 - return (vrf["name"] != "default" or self.shared_utils.underlay_routing_protocol == "none") and mlag_ibgp_peering + mlag_ibgp_peering = default(vrf.enable_mlag_ibgp_peering_vrfs, tenant.enable_mlag_ibgp_peering_vrfs) + return bool((vrf.name != "default" or self.shared_utils.underlay_routing_protocol == "none") and mlag_ibgp_peering) - def _mlag_ibgp_peering_vlan_vrf(self: AvdStructuredConfigNetworkServices, vrf: dict, tenant: dict) -> int | None: + def _mlag_ibgp_peering_vlan_vrf( + self: AvdStructuredConfigNetworkServices, + vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem, + tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem, + ) -> int | None: """ MLAG IBGP Peering VLANs per VRF. @@ -150,28 +149,32 @@ def _mlag_ibgp_peering_vlan_vrf(self: AvdStructuredConfigNetworkServices, vrf: d if not self._mlag_ibgp_peering_enabled(vrf, tenant): return None - if (mlag_ibgp_peering_vlan := get(vrf, "mlag_ibgp_peering_vlan")) is not None: + if (mlag_ibgp_peering_vlan := vrf.mlag_ibgp_peering_vlan) is not None: vlan_id = mlag_ibgp_peering_vlan else: - base_vlan = self.shared_utils.mlag_ibgp_peering_vrfs_base_vlan - vrf_id = vrf.get("vrf_id", vrf.get("vrf_vni")) + base_vlan = self.inputs.mlag_ibgp_peering_vrfs.base_vlan + vrf_id = default(vrf.vrf_id, vrf.vrf_vni) if vrf_id is None: - msg = f"Unable to assign MLAG VRF Peering VLAN for vrf {vrf['name']}.Set either 'mlag_ibgp_peering_vlan' or 'vrf_id' or 'vrf_vni' on the VRF" + msg = f"Unable to assign MLAG VRF Peering VLAN for vrf {vrf.name}.Set either 'mlag_ibgp_peering_vlan' or 'vrf_id' or 'vrf_vni' on the VRF" raise AristaAvdInvalidInputsError(msg) - vlan_id = base_vlan + int(vrf_id) - 1 + vlan_id = base_vlan + vrf_id - 1 return vlan_id - def _exclude_mlag_ibgp_peering_from_redistribute(self: AvdStructuredConfigNetworkServices, vrf: dict, tenant: dict) -> bool | None: + def _exclude_mlag_ibgp_peering_from_redistribute( + self: AvdStructuredConfigNetworkServices, + vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem, + tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem, + ) -> bool: """ Returns True if redistribute_connected is True and MLAG IBGP Peering subnet should be _excluded_ from redistribution for the given vrf/tenant. Does _not_ include checks if the peering is enabled at all, so that should be checked first. """ - if get(vrf, "redistribute_connected", True) is True: - return default(vrf.get("redistribute_mlag_ibgp_peering_vrfs"), tenant.get("redistribute_mlag_ibgp_peering_vrfs"), False) is False # noqa: FBT003 + if vrf.redistribute_connected: + return default(vrf.redistribute_mlag_ibgp_peering_vrfs, tenant.redistribute_mlag_ibgp_peering_vrfs) is False - return None + return False @cached_property def _configure_bgp_mlag_peer_group(self: AvdStructuredConfigNetworkServices) -> bool: @@ -186,14 +189,216 @@ def _configure_bgp_mlag_peer_group(self: AvdStructuredConfigNetworkServices) -> # Checking neighbors directly under BGP to cover VRF default case. for neighbor_settings in get(self._router_bgp_vrfs, "neighbors", default=[]): - if neighbor_settings.get("peer_group") == self.shared_utils.bgp_peer_groups["mlag_ipv4_underlay_peer"]["name"]: + if neighbor_settings.get("peer_group") == self.inputs.bgp_peer_groups.mlag_ipv4_underlay_peer.name: return True for bgp_vrf in get(self._router_bgp_vrfs, "vrfs", default=[]): if "neighbors" not in bgp_vrf: continue for neighbor_settings in bgp_vrf["neighbors"]: - if neighbor_settings.get("peer_group") == self.shared_utils.bgp_peer_groups["mlag_ipv4_underlay_peer"]["name"]: + if neighbor_settings.get("peer_group") == self.inputs.bgp_peer_groups.mlag_ipv4_underlay_peer.name: return True return False + + @cached_property + def _rt_admin_subfield(self: AvdStructuredConfigNetworkServices) -> str | None: + """ + Return a string with the route-target admin subfield unless set to "vrf_id" or "vrf_vni" or "id". + + Returns None if not set, since the calling functions will use + per-vlan numbers by default. + """ + admin_subfield = self.inputs.overlay_rt_type.admin_subfield + if admin_subfield is None: + return None + + if admin_subfield == "bgp_as": + return self.shared_utils.bgp_as + + if re_fullmatch(r"\d+", str(admin_subfield)): + return admin_subfield + + return None + + def get_vlan_mac_vrf_id( + self: AvdStructuredConfigNetworkServices, + vlan: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem + | EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.L2vlansItem, + tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem, + ) -> int: + mac_vrf_id_base = default(tenant.mac_vrf_id_base, tenant.mac_vrf_vni_base) + if mac_vrf_id_base is None: + msg = ( + "'rt_override' or 'vni_override' or 'mac_vrf_id_base' or 'mac_vrf_vni_base' must be set. " + f"Unable to set EVPN RD/RT for vlan {vlan.id} in Tenant '{vlan._tenant}'" + ) + raise AristaAvdInvalidInputsError(msg) + return mac_vrf_id_base + vlan.id + + def get_vlan_mac_vrf_vni( + self: AvdStructuredConfigNetworkServices, + vlan: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem + | EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.L2vlansItem, + tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem, + ) -> int: + mac_vrf_vni_base = default(tenant.mac_vrf_vni_base, tenant.mac_vrf_id_base) + if mac_vrf_vni_base is None: + msg = ( + "'rt_override' or 'vni_override' or 'mac_vrf_id_base' or 'mac_vrf_vni_base' must be set. " + f"Unable to set EVPN RD/RT for vlan {vlan.id} in Tenant '{vlan._tenant}'" + ) + raise AristaAvdInvalidInputsError(msg) + return mac_vrf_vni_base + vlan.id + + def get_vlan_rd( + self: AvdStructuredConfigNetworkServices, + vlan: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem + | EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.L2vlansItem, + tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem, + ) -> str: + """Return a string with the route-destinguisher for one VLAN.""" + rd_override = default(vlan.rd_override, vlan.rt_override, vlan.vni_override) + + if isinstance(rd_override, str) and ":" in rd_override: + return rd_override + + if rd_override is not None: + assigned_number_subfield = rd_override + elif self.inputs.overlay_rd_type.vlan_assigned_number_subfield == "mac_vrf_vni": + assigned_number_subfield = self.get_vlan_mac_vrf_vni(vlan, tenant) + elif self.inputs.overlay_rd_type.vlan_assigned_number_subfield == "vlan_id": + assigned_number_subfield = vlan.id + else: + assigned_number_subfield = self.get_vlan_mac_vrf_id(vlan, tenant) + + return f"{self.shared_utils.overlay_rd_type_admin_subfield}:{assigned_number_subfield}" + + def get_vlan_rt( + self: AvdStructuredConfigNetworkServices, + vlan: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem + | EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.L2vlansItem, + tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem, + ) -> str: + """Return a string with the route-target for one VLAN.""" + rt_override = default(vlan.rt_override, vlan.vni_override) + + if isinstance(rt_override, str) and ":" in rt_override: + return rt_override + + if self._rt_admin_subfield is not None: + admin_subfield = self._rt_admin_subfield + elif rt_override is not None: + admin_subfield = rt_override + elif self.inputs.overlay_rt_type.admin_subfield == "vrf_vni": + admin_subfield = self.get_vlan_mac_vrf_vni(vlan, tenant) + elif self.inputs.overlay_rt_type.admin_subfield == "id": + admin_subfield = vlan.id + else: + admin_subfield = self.get_vlan_mac_vrf_id(vlan, tenant) + + if rt_override is not None: + assigned_number_subfield = rt_override + elif self.inputs.overlay_rt_type.vlan_assigned_number_subfield == "mac_vrf_vni": + assigned_number_subfield = self.get_vlan_mac_vrf_vni(vlan, tenant) + elif self.inputs.overlay_rt_type.vlan_assigned_number_subfield == "vlan_id": + assigned_number_subfield = vlan.id + else: + assigned_number_subfield = self.get_vlan_mac_vrf_id(vlan, tenant) + + return f"{admin_subfield}:{assigned_number_subfield}" + + @cached_property + def _vrf_rt_admin_subfield(self: AvdStructuredConfigNetworkServices) -> str | None: + """ + Return a string with the VRF route-target admin subfield unless set to "vrf_id" or "vrf_vni" or "id". + + Returns None if not set, since the calling functions will use + per-vrf numbers by default. + """ + admin_subfield: str = default(self.inputs.overlay_rt_type.vrf_admin_subfield, self.inputs.overlay_rt_type.admin_subfield) + if admin_subfield == "bgp_as": + return self.shared_utils.bgp_as + + if re_fullmatch(r"\d+", admin_subfield): + return admin_subfield + + return None + + def get_vrf_rd(self: AvdStructuredConfigNetworkServices, vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem) -> str: + """Return a string with the route-destinguisher for one VRF.""" + rd_override = vrf.rd_override + + if rd_override is not None: + if ":" in rd_override: + return rd_override + + return f"{self.shared_utils.overlay_rd_type_vrf_admin_subfield}:{rd_override}" + + return f"{self.shared_utils.overlay_rd_type_vrf_admin_subfield}:{self.shared_utils.get_vrf_id(vrf)}" + + def get_vrf_rt(self: AvdStructuredConfigNetworkServices, vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem) -> str: + """Return a string with the route-target for one VRF.""" + rt_override = vrf.rt_override + + if rt_override is not None and ":" in rt_override: + return rt_override + + if self._vrf_rt_admin_subfield is not None: + admin_subfield = self._vrf_rt_admin_subfield + elif default(self.inputs.overlay_rt_type.vrf_admin_subfield, self.inputs.overlay_rt_type.admin_subfield) == "vrf_vni": + admin_subfield = self.shared_utils.get_vrf_vni(vrf) + else: + # Both for 'id' and 'vrf_id' options. + admin_subfield = self.shared_utils.get_vrf_id(vrf) + + if rt_override is not None: + return f"{admin_subfield}:{rt_override}" + + return f"{admin_subfield}:{self.shared_utils.get_vrf_id(vrf)}" + + def get_vlan_aware_bundle_rd( + self: AvdStructuredConfigNetworkServices, + id: int, # noqa: A002 + tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem, + is_vrf: bool, + rd_override: str | None = None, + ) -> str: + """Return a string with the route-destinguisher for one VLAN Aware Bundle.""" + admin_subfield = self.shared_utils.overlay_rd_type_vrf_admin_subfield if is_vrf else self.shared_utils.overlay_rd_type_admin_subfield + + if rd_override is not None: + if ":" in str(rd_override): + return rd_override + + return f"{admin_subfield}:{rd_override}" + + bundle_number = id + tenant.vlan_aware_bundle_number_base + return f"{admin_subfield}:{bundle_number}" + + def get_vlan_aware_bundle_rt( + self: AvdStructuredConfigNetworkServices, + id: int, # noqa: A002 + vni: int, + tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem, + is_vrf: bool, + rt_override: str | None = None, + ) -> str: + """Return a string with the route-target for one VLAN Aware Bundle.""" + if rt_override is not None and ":" in str(rt_override): + return rt_override + + bundle_number = id + tenant.vlan_aware_bundle_number_base + + if is_vrf and self._vrf_rt_admin_subfield is not None: + admin_subfield = self._vrf_rt_admin_subfield + elif is_vrf and default(self.inputs.overlay_rt_type.vrf_admin_subfield, self.inputs.overlay_rt_type.admin_subfield) == "vrf_vni": + admin_subfield = vni + else: + # Both for 'id' and 'vrf_id' options. + admin_subfield = bundle_number + + if rt_override is not None: + return f"{admin_subfield}:{rt_override}" + + return f"{admin_subfield}:{bundle_number}" diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/utils_wan.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/utils_wan.py index 35a60a7736f..daeca8ddd79 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/utils_wan.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/utils_wan.py @@ -6,8 +6,9 @@ from functools import cached_property from typing import TYPE_CHECKING, Literal -from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError -from pyavd._utils import get, get_all, get_ip_from_ip_prefix, get_item +from pyavd._eos_designs.schema import EosDesigns +from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError, AristaAvdMissingVariableError +from pyavd._utils import get, get_ip_from_ip_prefix from pyavd._utils.password_utils.password import simple_7_encrypt from pyavd.j2filters import natural_sort, range_expand @@ -23,50 +24,27 @@ class UtilsWanMixin: """ @cached_property - def _filtered_wan_vrfs(self: AvdStructuredConfigNetworkServices) -> list: + def _filtered_wan_vrfs(self: AvdStructuredConfigNetworkServices) -> EosDesigns.WanVirtualTopologies.Vrfs: """Loop through all the VRFs defined under `wan_virtual_topologies.vrfs` and returns a list of mode.""" - wan_vrfs = [] - - for vrf in get(self._hostvars, "wan_virtual_topologies.vrfs", []): - vrf_name = vrf["name"] - if vrf_name in self.shared_utils.vrfs or self.shared_utils.is_wan_server: - wan_vrf = { - "name": vrf_name, - "policy": get(vrf, "policy", default=self._default_wan_policy_name), - "wan_vni": get( - vrf, - "wan_vni", - required=True, - custom_error_msg=f"Required `wan_vni` is missing for VRF {vrf_name} under `wan_virtual_topologies.vrfs`.", - ), - } - - wan_vrfs.append(wan_vrf) + wan_vrfs = EosDesigns.WanVirtualTopologies.Vrfs( + vrf for vrf in self.inputs.wan_virtual_topologies.vrfs if vrf.name in self.shared_utils.vrfs or self.shared_utils.is_wan_server + ) # Check that default is in the list as it is required everywhere - if (vrf_default := get_item(wan_vrfs, "name", "default")) is None: - wan_vrfs.append( - { - "name": "default", - "policy": f"{self._default_wan_policy_name}-WITH-CP", - "wan_vni": 1, - "original_policy": self._default_wan_policy_name, - }, - ) - else: - vrf_default["original_policy"] = vrf_default["policy"] - vrf_default["policy"] = f"{vrf_default['policy']}-WITH-CP" + if "default" not in wan_vrfs: + wan_vrfs.append(EosDesigns.WanVirtualTopologies.VrfsItem(name="default", wan_vni=1)) return wan_vrfs @cached_property - def _wan_virtual_topologies_policies(self: AvdStructuredConfigNetworkServices) -> list: + def _wan_virtual_topologies_policies(self: AvdStructuredConfigNetworkServices) -> EosDesigns.WanVirtualTopologies.Policies: """This function parses the input data and append the default-policy if not already present.""" - policies = get(self._hostvars, "wan_virtual_topologies.policies", default=[]) # If not overwritten, inject the default policy in case it is required for one of the VRFs - if get_item(policies, "name", self._default_wan_policy_name) is None: - policies.append(self._default_wan_policy) + if self._default_wan_policy_name in self.inputs.wan_virtual_topologies.policies: + return self.inputs.wan_virtual_topologies.policies + policies = self.inputs.wan_virtual_topologies.policies._deepcopy() + policies.append(self._default_wan_policy) return policies @cached_property @@ -86,21 +64,17 @@ def _filtered_wan_policies(self: AvdStructuredConfigNetworkServices) -> list: for vrf in self._filtered_wan_vrfs: # Need to handle VRF default differently and lookup for the original policy - lookup_name = get(vrf, "original_policy", default=vrf["policy"]) - vrf_policy = get_item( - self._wan_virtual_topologies_policies, - "name", - lookup_name, - required=True, - custom_error_msg=( - f"The policy {lookup_name} applied to vrf {vrf['name']} under `wan_virtual_topologies.vrfs` is not " + if vrf.policy not in self._wan_virtual_topologies_policies: + msg = ( + f"The policy {vrf.policy} applied to vrf {vrf.name} under `wan_virtual_topologies.vrfs` is not " "defined under `wan_virtual_topologies.policies`." - ), - ).copy() + ) + raise AristaAvdInvalidInputsError(msg) - vrf_policy["profile_prefix"] = lookup_name + vrf_policy = self._wan_virtual_topologies_policies[vrf.policy]._as_dict() + vrf_policy["profile_prefix"] = vrf.policy - if vrf["name"] == "default": + if vrf.name == "default": vrf_policy["is_default"] = True vrf_policy["name"] = f"{vrf_policy['name']}-WITH-CP" @@ -130,7 +104,7 @@ def _update_policy_match_statements(self: AvdStructuredConfigNetworkServices, po if ( load_balance_policy := self._generate_wan_load_balance_policy( load_balance_policy_name, - control_plane_virtual_topology, + control_plane_virtual_topology._as_dict(), policy["name"], ) ) is None: @@ -140,9 +114,9 @@ def _update_policy_match_statements(self: AvdStructuredConfigNetworkServices, po { "application_profile": self._wan_control_plane_application_profile_name, "avt_profile": self._wan_control_plane_profile_name, - "internet_exit_policy_name": get(control_plane_virtual_topology, "internet_exit.policy"), - "traffic_class": get(control_plane_virtual_topology, "traffic_class"), - "dscp": get(control_plane_virtual_topology, "dscp"), + "internet_exit_policy_name": control_plane_virtual_topology.internet_exit.policy, + "traffic_class": control_plane_virtual_topology.traffic_class, + "dscp": control_plane_virtual_topology.dscp, "load_balance_policy": load_balance_policy, "id": 254, }, @@ -217,13 +191,11 @@ def _update_policy_match_statements(self: AvdStructuredConfigNetworkServices, po load_balance_policy = self._generate_wan_load_balance_policy(load_balance_policy_name, default_virtual_topology, context_path) if not load_balance_policy: msg = ( - f"The `default_virtual_topology` path-groups configuration for `wan_virtual_toplogies.policies[{policy['name']}]` produces " + f"The `default_virtual_topology` path-groups configuration for `wan_virtual_topologies.policies[{policy['name']}]` produces " "an empty load-balancing policy. Make sure at least one path-group present on the device is allowed in the " "`default_virtual_topology` path-groups." ) - raise AristaAvdError( - msg, - ) + raise AristaAvdError(msg) application_profile = get(default_virtual_topology, "application_profile", default="default") default_match = { @@ -239,12 +211,10 @@ def _update_policy_match_statements(self: AvdStructuredConfigNetworkServices, po if not matches and not default_match: # The policy is empty but should be assigned to a VRF msg = ( - f"The policy `wan_virtual_toplogies.policies[{policy['name']}]` cannot match any traffic but is assigned to a VRF. " + f"The policy `wan_virtual_topologies.policies[{policy['name']}]` cannot match any traffic but is assigned to a VRF. " "Make sure at least one path-group present on the device is used in the policy." ) - raise AristaAvdError( - msg, - ) + raise AristaAvdError(msg) policy["matches"] = matches policy["default_match"] = default_match @@ -269,7 +239,7 @@ def _generate_wan_load_balance_policy(self: AvdStructuredConfigNetworkServices, **get(input_dict, "constraints", default={}), } - if self.shared_utils.wan_mode == "cv-pathfinder": + if self.inputs.wan_mode == "cv-pathfinder": wan_load_balance_policy["lowest_hop_count"] = get(input_dict, "lowest_hop_count") # An entry is composed of a list of path-groups in `names` and a `priority` @@ -287,17 +257,14 @@ def _generate_wan_load_balance_policy(self: AvdStructuredConfigNetworkServices, for path_group_name in entry_path_groups: if (priority := policy_entry_priority) is None: # No preference defined at the policy level, need to retrieve the default preference - wan_path_group = get_item( - self.shared_utils.wan_path_groups, - "name", - path_group_name, - required=True, - custom_error_msg=( + if path_group_name not in self.inputs.wan_path_groups: + msg = ( f"Failed to retrieve path-group {path_group_name} from `wan_path_groups` when generating load balance policy {name}. " f"Verify the path-groups defined under {context_path}." - ), - ) - priority = self._path_group_preference_to_eos_priority(wan_path_group["default_preference"], f"wan_path_groups[{wan_path_group['name']}]") + ) + raise AristaAvdInvalidInputsError(msg) + wan_path_group = self.inputs.wan_path_groups[path_group_name] + priority = self._path_group_preference_to_eos_priority(wan_path_group.default_preference, f"wan_path_groups[{wan_path_group.name}]") # Skip path-group on this device if not present on the router except for pathfinders if self.shared_utils.is_wan_client and path_group_name not in self.shared_utils.wan_local_path_group_names: @@ -319,7 +286,7 @@ def _generate_wan_load_balance_policy(self: AvdStructuredConfigNetworkServices, if self.shared_utils.wan_ha or self.shared_utils.is_cv_pathfinder_server: # Adding HA path-group with priority 1 - wan_load_balance_policy["path_groups"].append({"name": self.shared_utils.wan_ha_path_group_name}) + wan_load_balance_policy["path_groups"].append({"name": self.inputs.wan_ha.lan_ha_path_group_name}) return wan_load_balance_policy @@ -348,9 +315,7 @@ def _path_group_preference_to_eos_priority(self: AvdStructuredConfigNetworkServi f"Invalid value '{path_group_preference}' for Path-Group preference - should be either 'preferred', " f"'alternate' or an integer[1-65535] for {context_path}." ) - raise AristaAvdError( - msg, - ) + raise AristaAvdError(msg) return priority @@ -360,16 +325,14 @@ def _default_wan_policy_name(self: AvdStructuredConfigNetworkServices) -> str: return "DEFAULT-POLICY" @cached_property - def _default_policy_path_group_names(self: AvdStructuredConfigNetworkServices) -> list: + def _default_policy_path_group_names(self: AvdStructuredConfigNetworkServices) -> list[str]: """ Return a list of path group names for the default policy. Return the list of path-groups to consider when generating a default policy with AVD whether for the default policy or the special Control-plane policy. """ - path_group_names = { - path_group["name"] for path_group in self.shared_utils.wan_path_groups if not get(path_group, "excluded_from_default_policy", default=False) - } + path_group_names = {path_group.name for path_group in self.inputs.wan_path_groups if not path_group.excluded_from_default_policy} if not path_group_names.intersection(self.shared_utils.wan_local_path_group_names): # No common path-group between this device local path-groups and the available path-group for the default policy msg = ( @@ -377,23 +340,31 @@ def _default_policy_path_group_names(self: AvdStructuredConfigNetworkServices) - "is eligible to be included. Make sure that at least one path-group for the device is not configured with " "`excluded_from_default_policy: true` under `wan_path_groups`." ) - raise AristaAvdError( - msg, - ) + raise AristaAvdError(msg) return natural_sort(path_group_names) @cached_property - def _default_wan_policy(self: AvdStructuredConfigNetworkServices) -> dict: + def _default_wan_policy(self: AvdStructuredConfigNetworkServices) -> EosDesigns.WanVirtualTopologies.PoliciesItem: """ Returning policy containing all path groups not excluded from default policy. If no policy is defined for a VRF under 'wan_virtual_topologies.vrfs', a default policy named DEFAULT-POLICY is used where all traffic is matched in the default category and distributed amongst all path-groups. """ - return { - "name": self._default_wan_policy_name, - "default_virtual_topology": {"path_groups": [{"names": self._default_policy_path_group_names}]}, - } + return EosDesigns.WanVirtualTopologies.PoliciesItem( + name=self._default_wan_policy_name, + default_virtual_topology=EosDesigns.WanVirtualTopologies.PoliciesItem.DefaultVirtualTopology( + path_groups=EosDesigns.WanVirtualTopologies.PoliciesItem.DefaultVirtualTopology.PathGroups( + [ + EosDesigns.WanVirtualTopologies.PoliciesItem.DefaultVirtualTopology.PathGroupsItem( + names=EosDesigns.WanVirtualTopologies.PoliciesItem.DefaultVirtualTopology.PathGroupsItem.Names( + self._default_policy_path_group_names + ) + ) + ] + ) + ), + ) def _default_profile_name(self: AvdStructuredConfigNetworkServices, profile_name: str, application_profile: str) -> str: """ @@ -404,38 +375,47 @@ def _default_profile_name(self: AvdStructuredConfigNetworkServices, profile_name return f"{profile_name}-{application_profile}" @cached_property - def _wan_control_plane_virtual_topology(self: AvdStructuredConfigNetworkServices) -> dict: + def _wan_control_plane_virtual_topology(self: AvdStructuredConfigNetworkServices) -> EosDesigns.WanVirtualTopologies.ControlPlaneVirtualTopology: """ Return the Control plane virtual topology or the default one. The default control_plane_virtual_topology, excluding path_groups with excluded_from_default_policy """ - if (control_plane_virtual_topology := get(self._hostvars, "wan_virtual_topologies.control_plane_virtual_topology")) is None: - path_groups = self._default_policy_path_group_names - if self.shared_utils.is_wan_client: - # Filter only the path-groups connected to pathfinder - path_groups = [path_group for path_group in path_groups if path_group in self._local_path_groups_connected_to_pathfinder] - control_plane_virtual_topology = {"path_groups": [{"names": path_groups}]} - return control_plane_virtual_topology + if self.inputs.wan_virtual_topologies.control_plane_virtual_topology: + return self.inputs.wan_virtual_topologies.control_plane_virtual_topology + + path_groups = self._default_policy_path_group_names + if self.shared_utils.is_wan_client: + # Filter only the path-groups connected to pathfinder + path_groups = [path_group for path_group in path_groups if path_group in self._local_path_groups_connected_to_pathfinder] + return EosDesigns.WanVirtualTopologies.ControlPlaneVirtualTopology( + path_groups=EosDesigns.WanVirtualTopologies.ControlPlaneVirtualTopology.PathGroups( + [ + EosDesigns.WanVirtualTopologies.ControlPlaneVirtualTopology.PathGroupsItem( + names=EosDesigns.WanVirtualTopologies.ControlPlaneVirtualTopology.PathGroupsItem.Names(path_groups) + ) + ] + ) + ) @cached_property def _wan_control_plane_profile_name(self: AvdStructuredConfigNetworkServices) -> str: """Control plane profile name.""" - vrf_default_policy_name = get(get_item(self._filtered_wan_vrfs, "name", "default"), "original_policy") - return get(self._wan_control_plane_virtual_topology, "name", default=f"{vrf_default_policy_name}-CONTROL-PLANE") + vrf_default_policy_name = self._filtered_wan_vrfs["default"].policy + return self._wan_control_plane_virtual_topology.name or f"{vrf_default_policy_name}-CONTROL-PLANE" @cached_property def _wan_control_plane_application_profile_name(self: AvdStructuredConfigNetworkServices) -> str: """Control plane application profile name.""" - return get(self._hostvars, "wan_virtual_topologies.control_plane_virtual_topology.application_profile", default="APP-PROFILE-CONTROL-PLANE") + return self.inputs.wan_virtual_topologies.control_plane_virtual_topology.application_profile @cached_property def _local_path_groups_connected_to_pathfinder(self: AvdStructuredConfigNetworkServices) -> list: """Return list of names of local path_groups connected to pathfinder.""" return [ - path_group["name"] + path_group.name for path_group in self.shared_utils.wan_local_path_groups - if any(wan_interface["connected_to_pathfinder"] for wan_interface in path_group["interfaces"]) + if any(wan_interface["connected_to_pathfinder"] for wan_interface in path_group._interfaces) ] @cached_property @@ -456,15 +436,15 @@ def _svi_acls(self: AvdStructuredConfigNetworkServices) -> dict[str, dict[str, d svi_acls = {} for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: - for svi in vrf["svis"]: - ipv4_acl_in = get(svi, "ipv4_acl_in") - ipv4_acl_out = get(svi, "ipv4_acl_out") + for vrf in tenant.vrfs: + for svi in vrf.svis: + ipv4_acl_in = svi.ipv4_acl_in + ipv4_acl_out = svi.ipv4_acl_out if ipv4_acl_in is None and ipv4_acl_out is None: continue - interface_name = f"Vlan{svi['id']}" - interface_ip: str | None = svi.get("ip_address_virtual") + interface_name = f"Vlan{svi.id}" + interface_ip = svi.ip_address_virtual if interface_ip is not None and "/" in interface_ip: interface_ip = get_ip_from_ip_prefix(interface_ip) @@ -473,13 +453,13 @@ def _svi_acls(self: AvdStructuredConfigNetworkServices) -> dict[str, dict[str, d name=ipv4_acl_in, interface_name=interface_name, interface_ip=interface_ip, - ) + )._as_dict() if ipv4_acl_out is not None: svi_acls.setdefault(interface_name, {})["ipv4_acl_out"] = self.shared_utils.get_ipv4_acl( name=ipv4_acl_out, interface_name=interface_name, interface_ip=interface_ip, - ) + )._as_dict() return svi_acls @@ -538,7 +518,7 @@ def get_internet_exit_nat_pool_and_profile( @cached_property def _filtered_internet_exit_policy_types(self: AvdStructuredConfigNetworkServices) -> list: - return sorted({internet_exit_policy["type"] for internet_exit_policy in self._filtered_internet_exit_policies}) + return sorted({internet_exit_policy.type for internet_exit_policy, _connections in self._filtered_internet_exit_policies_and_connections}) @cached_property def _l3_interface_acls(self: AvdStructuredConfigNetworkServices) -> dict | None: @@ -559,18 +539,18 @@ def _l3_interface_acls(self: AvdStructuredConfigNetworkServices) -> dict | None: l3_interface_acls = {} for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: - for l3_interface in vrf["l3_interfaces"]: - for interface_idx, interface in enumerate(l3_interface["interfaces"]): - if l3_interface["nodes"][interface_idx] != self.shared_utils.hostname: + for vrf in tenant.vrfs: + for l3_interface in vrf.l3_interfaces: + for interface_idx, interface in enumerate(l3_interface.interfaces): + if l3_interface.nodes[interface_idx] != self.shared_utils.hostname: continue - ipv4_acl_in = get(l3_interface, "ipv4_acl_in") - ipv4_acl_out = get(l3_interface, "ipv4_acl_out") + ipv4_acl_in = l3_interface.ipv4_acl_in + ipv4_acl_out = l3_interface.ipv4_acl_out if ipv4_acl_in is None and ipv4_acl_out is None: continue interface_name = interface - interface_ip: str | None = l3_interface["ip_addresses"][interface_idx] + interface_ip: str | None = l3_interface.ip_addresses[interface_idx] if interface_ip is not None: interface_ip = get_ip_from_ip_prefix(interface_ip) if ipv4_acl_in is not None: @@ -578,48 +558,48 @@ def _l3_interface_acls(self: AvdStructuredConfigNetworkServices) -> dict | None: name=ipv4_acl_in, interface_name=interface_name, interface_ip=interface_ip, - ) + )._as_dict() if ipv4_acl_out is not None: l3_interface_acls.setdefault(interface_name, {})["ipv4_acl_out"] = self.shared_utils.get_ipv4_acl( name=ipv4_acl_out, interface_name=interface_name, interface_ip=interface_ip, - ) + )._as_dict() return l3_interface_acls @cached_property - def _filtered_internet_exit_policies(self: AvdStructuredConfigNetworkServices) -> list: + def _filtered_internet_exit_policies_and_connections( + self: AvdStructuredConfigNetworkServices, + ) -> list[tuple[EosDesigns.CvPathfinderInternetExitPoliciesItem, list[dict]]]: """ Only supported for CV Pathfinder Edge routers. Returns an empty list for pathfinders. - Parse self._filtered_wan_policies looking to internet_exit_policies. - Verify each internet_exit_policy is present in inputs `cv_pathfinder_internet_exit_policies`. - get_internet_exit_connections and insert into the policy dict. - - Return the list of relevant internet_exit_policies. + + Return the list of relevant internet_exit_policies together with the connections for that policy. """ if not self.shared_utils.is_cv_pathfinder_client: return [] internet_exit_policy_names = set() - candidate_internet_exit_policies = [] - configured_internet_exit_policies = get(self._hostvars, "cv_pathfinder_internet_exit_policies", []) + candidate_internet_exit_policies: list[EosDesigns.CvPathfinderInternetExitPoliciesItem] = [] + configured_internet_exit_policies = self.inputs.cv_pathfinder_internet_exit_policies for policy in self._filtered_wan_policies: for match in get(policy, "matches", default=[]): internet_exit_policy_name = match.get("internet_exit_policy_name") if not internet_exit_policy_name or internet_exit_policy_name in internet_exit_policy_names: continue - internet_exit_policy = get_item( - configured_internet_exit_policies, - "name", - internet_exit_policy_name, - required=True, - custom_error_msg=( + if internet_exit_policy_name not in configured_internet_exit_policies: + msg = ( f"The internet exit policy {internet_exit_policy_name} configured under " f"`wan_virtual_topologies.policies[name={policy['name']}].internet_exit.policy` " "is not defined under `cv_pathfinder_internet_exit_policies`." - ), - ).copy() + ) + raise AristaAvdInvalidInputsError(msg) + internet_exit_policy = configured_internet_exit_policies[internet_exit_policy_name] internet_exit_policy_names.add(internet_exit_policy_name) candidate_internet_exit_policies.append(internet_exit_policy) @@ -627,17 +607,14 @@ def _filtered_internet_exit_policies(self: AvdStructuredConfigNetworkServices) - internet_exit_policy_name = default_match.get("internet_exit_policy_name") if not internet_exit_policy_name or internet_exit_policy_name in internet_exit_policy_names: continue - internet_exit_policy = get_item( - configured_internet_exit_policies, - "name", - internet_exit_policy_name, - required=True, - custom_error_msg=( + if internet_exit_policy_name not in configured_internet_exit_policies: + msg = ( f"The internet exit policy {internet_exit_policy_name} configured under " f"`wan_virtual_topologies.policies[name={policy['name']}].internet_exit.policy` " "is not defined under `cv_pathfinder_internet_exit_policies`." - ), - ).copy() + ) + raise AristaAvdInvalidInputsError(msg) + internet_exit_policy = configured_internet_exit_policies[internet_exit_policy_name] internet_exit_policy_names.add(internet_exit_policy_name) candidate_internet_exit_policies.append(internet_exit_policy) @@ -647,135 +624,143 @@ def _filtered_internet_exit_policies(self: AvdStructuredConfigNetworkServices) - internet_exit_policies = [] for internet_exit_policy in candidate_internet_exit_policies: - local_interfaces = [ - wan_interface - for wan_interface in self.shared_utils.wan_interfaces - if internet_exit_policy["name"] in get_all(wan_interface, "cv_pathfinder_internet_exit.policies.name") - ] + local_interfaces = EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem.L3Interfaces( + [ + wan_interface + for wan_interface in self.shared_utils.wan_interfaces + if internet_exit_policy.name in wan_interface.cv_pathfinder_internet_exit.policies + ] + ) if not local_interfaces: # No local interface for this policy # TODO: Decide if we should raise here instead continue - internet_exit_policy["connections"] = self.get_internet_exit_connections(internet_exit_policy, local_interfaces) - internet_exit_policies.append(internet_exit_policy) + connections = self.get_internet_exit_connections(internet_exit_policy, local_interfaces) + internet_exit_policies.append((internet_exit_policy, connections)) return internet_exit_policies - def get_internet_exit_connections(self: AvdStructuredConfigNetworkServices, internet_exit_policy: dict, local_interfaces: list[dict]) -> list: + def get_internet_exit_connections( + self: AvdStructuredConfigNetworkServices, + internet_exit_policy: EosDesigns.CvPathfinderInternetExitPoliciesItem, + local_interfaces: EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem.L3Interfaces, + ) -> list: """ Return a list of connections (dicts) for the given internet_exit_policy. These are useful for easy creation of connectivity-monitor, service-insertion connections, exit-groups, tunnels etc. """ - policy_name = internet_exit_policy["name"] - policy_type = internet_exit_policy["type"] - - if policy_type == "direct": + if internet_exit_policy.type == "direct": return self.get_direct_internet_exit_connections(internet_exit_policy, local_interfaces) - if policy_type == "zscaler": + if internet_exit_policy.type == "zscaler": return self.get_zscaler_internet_exit_connections(internet_exit_policy, local_interfaces) - msg = f"Unsupported type '{policy_type}' found in cv_pathfinder_internet_exit[name={policy_name}]." + msg = f"Unsupported type '{internet_exit_policy.type}' found in cv_pathfinder_internet_exit[name={internet_exit_policy.name}]." raise AristaAvdError(msg) - def get_direct_internet_exit_connections(self: AvdStructuredConfigNetworkServices, internet_exit_policy: dict, local_interfaces: list[dict]) -> list: + def get_direct_internet_exit_connections( + self: AvdStructuredConfigNetworkServices, + internet_exit_policy: EosDesigns.CvPathfinderInternetExitPoliciesItem, + local_interfaces: EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem.L3Interfaces, + ) -> list[dict]: """Return a list of connections (dicts) for the given internet_exit_policy of type direct.""" - if get(internet_exit_policy, "type") != "direct": + if internet_exit_policy.type != "direct": return [] connections = [] # Build internet exit connection for each local interface (wan_interface) for wan_interface in local_interfaces: - wan_interface_internet_exit_policies = get(wan_interface, "cv_pathfinder_internet_exit.policies", default=[]) - if get_item(wan_interface_internet_exit_policies, "name", internet_exit_policy["name"]) is None: + if internet_exit_policy.name not in wan_interface.cv_pathfinder_internet_exit.policies: continue - if not wan_interface.get("peer_ip"): + if not wan_interface.peer_ip: msg = ( - f"{wan_interface['name']} peer_ip needs to be set. When using wan interface " + f"{wan_interface.name} peer_ip needs to be set. When using wan interface " "for direct type internet exit, peer_ip is used for nexthop, and connectivity monitoring." ) raise AristaAvdInvalidInputsError(msg) # wan interface ip will be used for acl, hence raise error if ip is not available - if (ip_address := wan_interface.get("ip_address")) == "dhcp" and not (ip_address := wan_interface.get("dhcp_ip")): + if (ip_address := wan_interface.ip_address) == "dhcp" and not (ip_address := wan_interface.dhcp_ip): msg = ( - f"{wan_interface['name']} 'dhcp_ip' needs to be set. When using WAN interface for 'direct' type Internet exit, " + f"{wan_interface.name} 'dhcp_ip' needs to be set. When using WAN interface for 'direct' type Internet exit, " "'dhcp_ip' is used in the NAT ACL." ) raise AristaAvdInvalidInputsError(msg) - sanitized_interface_name = self.shared_utils.sanitize_interface_name(wan_interface["name"]) + sanitized_interface_name = self.shared_utils.sanitize_interface_name(wan_interface.name) connections.append( { "type": "ethernet", "name": f"IE-{sanitized_interface_name}", "source_interface_ip_address": ip_address, "monitor_name": f"IE-{sanitized_interface_name}", - "monitor_host": wan_interface["peer_ip"], - "next_hop": wan_interface["peer_ip"], - "source_interface": wan_interface["name"], - "description": f"Internet Exit {internet_exit_policy['name']}", - "exit_group": f"{internet_exit_policy['name']}", + "monitor_host": wan_interface.peer_ip, + "next_hop": wan_interface.peer_ip, + "source_interface": wan_interface.name, + "description": f"Internet Exit {internet_exit_policy.name}", + "exit_group": f"{internet_exit_policy.name}", }, ) - return connections - def get_zscaler_internet_exit_connections(self: AvdStructuredConfigNetworkServices, internet_exit_policy: dict, local_interfaces: list[dict]) -> list: + def get_zscaler_internet_exit_connections( + self: AvdStructuredConfigNetworkServices, + internet_exit_policy: EosDesigns.CvPathfinderInternetExitPoliciesItem, + local_interfaces: EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem.L3Interfaces, + ) -> list: """Return a list of connections (dicts) for the given internet_exit_policy of type zscaler.""" - if get(internet_exit_policy, "type") != "zscaler": + if internet_exit_policy.type != "zscaler": return [] - policy_name = internet_exit_policy["name"] + policy_name = internet_exit_policy.name - cloud_name = get(self._zscaler_endpoints, "cloud_name", required=True) + cloud_name = self._zscaler_endpoints.cloud_name connections = [] # Build internet exit connection for each local interface (wan_interface) for wan_interface in local_interfaces: - wan_interface_internet_exit_policies = get(wan_interface, "cv_pathfinder_internet_exit.policies", default=[]) - if (interface_policy_config := get_item(wan_interface_internet_exit_policies, "name", internet_exit_policy["name"])) is None: + if policy_name not in wan_interface.cv_pathfinder_internet_exit.policies: continue + interface_policy_config = wan_interface.cv_pathfinder_internet_exit.policies[policy_name] + + if not wan_interface.peer_ip: + msg = f"The configured internet-exit policy requires `peer_ip` configured under the WAN Interface {wan_interface.name}." + raise AristaAvdInvalidInputsError(msg) + connection_base = { "type": "tunnel", - "source_interface": wan_interface["name"], - "next_hop": get( - wan_interface, - "peer_ip", - required=True, - custom_error_msg=f"The configured internet-exit policy requires `peer_ip` configured under the WAN Interface {wan_interface['name']}.", - ), + "source_interface": wan_interface.name, + "next_hop": wan_interface.peer_ip, # Accepting SonarLint issue: The URL is just for verifying connectivity. No data is passed. "monitor_url": f"http://gateway.{cloud_name}.net/vpntest", # NOSONAR } - tunnel_interface_numbers = get(interface_policy_config, "tunnel_interface_numbers") - if tunnel_interface_numbers is None: + if interface_policy_config.tunnel_interface_numbers is None: msg = ( - f"{wan_interface['name']}.cv_pathfinder_internet_exit.policies[{internet_exit_policy['name']}]." + f"{wan_interface.name}.cv_pathfinder_internet_exit.policies[{internet_exit_policy.name}]." "tunnel_interface_numbers needs to be set, when using wan interface for zscaler type internet exit." ) raise AristaAvdInvalidInputsError(msg) - tunnel_id_range = range_expand(tunnel_interface_numbers) + tunnel_id_range = range_expand(interface_policy_config.tunnel_interface_numbers) - zscaler_endpoint_keys = ("primary", "secondary", "tertiary") - for index, zscaler_endpoint_key in enumerate(zscaler_endpoint_keys): - if zscaler_endpoint_key not in self._zscaler_endpoints: + zscaler_endpoints = (self._zscaler_endpoints.primary, self._zscaler_endpoints.secondary, self._zscaler_endpoints.tertiary) + for index, zscaler_endpoint in enumerate(zscaler_endpoints): + if not zscaler_endpoint: continue - zscaler_endpoint = self._zscaler_endpoints[zscaler_endpoint_key] + preference = ("primary", "secondary", "tertiary")[index] # PRI, SEC, TER used for groups # TODO: consider if we should use DC names as group suffix. - suffix = zscaler_endpoint_key[0:3].upper() + suffix = preference[0:3].upper() - destination_ip = zscaler_endpoint["ip_address"] + destination_ip = zscaler_endpoint.ip_address tunnel_id = tunnel_id_range[index] connections.append( { @@ -790,21 +775,27 @@ def get_zscaler_internet_exit_connections(self: AvdStructuredConfigNetworkServic "ipsec_profile": f"IE-{policy_name}-PROFILE", "description": f"Internet Exit {policy_name} {suffix}", "exit_group": f"{policy_name}_{suffix}", - "preference": zscaler_endpoint_key, + "preference": preference, "suffix": suffix, - "endpoint": zscaler_endpoint, + "endpoint": zscaler_endpoint._as_dict(), }, ) - return connections - def _get_ipsec_credentials(self: AvdStructuredConfigNetworkServices, internet_exit_policy: dict) -> tuple[str, str]: + def _get_ipsec_credentials( + self: AvdStructuredConfigNetworkServices, internet_exit_policy: EosDesigns.CvPathfinderInternetExitPoliciesItem + ) -> tuple[str, str]: """Returns ufqdn, shared_key based on various details from the given internet_exit_policy.""" - policy_name = internet_exit_policy["name"] - domain_name = get(internet_exit_policy, "zscaler.domain_name", required=True) - ipsec_key_salt = get(internet_exit_policy, "zscaler.ipsec_key_salt", required=True) - ipsec_key = self._generate_ipsec_key(name=policy_name, salt=ipsec_key_salt) - ufqdn = f"{self.shared_utils.hostname}_{policy_name}@{domain_name}" + if not internet_exit_policy.zscaler.domain_name: + msg = "zscaler.domain_name" + raise AristaAvdMissingVariableError(msg) + + if not internet_exit_policy.zscaler.ipsec_key_salt: + msg = "zscaler.ipsec_key_salt" + raise AristaAvdMissingVariableError(msg) + + ipsec_key = self._generate_ipsec_key(name=internet_exit_policy.name, salt=internet_exit_policy.zscaler.ipsec_key_salt) + ufqdn = f"{self.shared_utils.hostname}_{internet_exit_policy.name}@{internet_exit_policy.zscaler.domain_name}" return ufqdn, ipsec_key def _generate_ipsec_key(self: AvdStructuredConfigNetworkServices, name: str, salt: str) -> str: diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/utils_zscaler.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/utils_zscaler.py index 57e89896af8..5a423cbeea0 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/utils_zscaler.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/utils_zscaler.py @@ -11,8 +11,8 @@ from pyavd._cv.client import CVClient from pyavd._cv.workflows.models import CVDevice from pyavd._cv.workflows.verify_devices_on_cv import verify_devices_in_cloudvision_inventory -from pyavd._errors import AristaAvdError -from pyavd._utils import get +from pyavd._eos_designs.schema import EosDesigns +from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError if TYPE_CHECKING: from pyavd._cv.api.arista.swg.v1 import Location, VpnEndpoint @@ -30,19 +30,15 @@ class UtilsZscalerMixin: """ @cached_property - def _zscaler_endpoints(self: AvdStructuredConfigNetworkServices) -> dict: + def _zscaler_endpoints(self: AvdStructuredConfigNetworkServices) -> EosDesigns.ZscalerEndpoints: """ Returns zscaler_endpoints data model built via CloudVision API calls, unless they are provided in the input variables. Should only be called for CV Pathfinder Client devices. """ - zscaler_endpoints = get(self._hostvars, "zscaler_endpoints") - if zscaler_endpoints is not None: - return zscaler_endpoints + return self.inputs.zscaler_endpoints or asyncio.run(self._generate_zscaler_endpoints()) - return asyncio.run(self._generate_zscaler_endpoints()) or {} - - async def _generate_zscaler_endpoints(self: AvdStructuredConfigNetworkServices) -> dict: + async def _generate_zscaler_endpoints(self: AvdStructuredConfigNetworkServices) -> EosDesigns.ZscalerEndpoints: """ Call CloudVision SWG APIs to generate the zscaler_endpoints model. @@ -51,17 +47,20 @@ async def _generate_zscaler_endpoints(self: AvdStructuredConfigNetworkServices) TODO: Add support for cv_verify_certs """ context = "The WAN Internet-exit integration with Zscaler fetches information from CloudVision" - cv_server = get(self._hostvars, "cv_server", required=True, custom_error_msg=f"{context} and requires 'cv_server' to be set.") - cv_token = get(self._hostvars, "cv_token", required=True, custom_error_msg=f"{context} and requires 'cv_server' to be set.") - wan_site_location = get( - self.shared_utils.wan_site, - "location", - required=True, - custom_error_msg=( - f"{context} and requires 'cv_pathfinder_regions[name={self.shared_utils.wan_region['name']}]" - f".sites[name={self.shared_utils.wan_site['name']}].location' to be set." - ), - ) + if not (cv_server := self.inputs.cv_server): + msg = f"{context} and requires 'cv_server' to be set." + raise AristaAvdInvalidInputsError(msg) + if not (cv_token := self.inputs.cv_token): + msg = f"{context} and requires 'cv_token' to be set." + raise AristaAvdInvalidInputsError(msg) + + if self.shared_utils.wan_site is None or not self.shared_utils.wan_site.location: + region_key = f"name={self.shared_utils.wan_region.name}" if self.shared_utils.wan_region is not None else "" + site_key = f"name={self.shared_utils.wan_site.name}" if self.shared_utils.wan_site is not None else "" + msg = f"{context} and requires 'cv_pathfinder_regions[{region_key}]" f".sites[{site_key}].location' to be set." + raise AristaAvdInvalidInputsError(msg) + + wan_site_location = self.shared_utils.wan_site.location async with CVClient(servers=[cv_server], token=cv_token) as cv_client: cv_device = CVDevice(self.shared_utils.hostname, self.shared_utils.serial_number, self.shared_utils.system_mac_address) @@ -79,38 +78,41 @@ async def _generate_zscaler_endpoints(self: AvdStructuredConfigNetworkServices) f"{context} but found more than one device named '{self.shared_utils.hostname}' on the server '{cv_server}'. " "Set 'serial_number' for the device in AVD vars, to ensure a unique match." ) - raise AristaAvdError( - msg, - ) + raise AristaAvdError(msg) device_id: str = cv_inventory_devices[0].serial_number request_time, _ = await cv_client.set_swg_device(device_id=device_id, service="zscaler", location=wan_site_location) cv_endpoint_status = await cv_client.wait_for_swg_endpoint_status(device_id=device_id, service="zscaler", start_time=request_time) device_location: Location = cv_endpoint_status.device_location - zscaler_endpoints = { - "cloud_name": cv_endpoint_status.cloud_name, - "device_location": { - "city": device_location.city, - "country": device_location.country, - }, - } + zscaler_endpoints = EosDesigns.ZscalerEndpoints( + cloud_name=cv_endpoint_status.cloud_name, + device_location=EosDesigns.ZscalerEndpoints.DeviceLocation(city=device_location.city, country=device_location.country), + ) if not getattr(cv_endpoint_status, "vpn_endpoints", None) or not getattr(cv_endpoint_status.vpn_endpoints, "values", None): msg = f"{context} but did not get any IPsec Tunnel endpoints back from the Zscaler API." raise AristaAvdError(msg) - for key in ("primary", "secondary", "tertiary"): + for key, cls in ( + ("primary", EosDesigns.ZscalerEndpoints.Primary), + ("secondary", EosDesigns.ZscalerEndpoints.Secondary), + ("tertiary", EosDesigns.ZscalerEndpoints.Tertiary), + ): if key in cv_endpoint_status.vpn_endpoints.values: vpn_endpoint: VpnEndpoint = cv_endpoint_status.vpn_endpoints.values[key] location: Location = vpn_endpoint.endpoint_location - zscaler_endpoints[key] = { - "ip_address": vpn_endpoint.ip_address.value, - "datacenter": vpn_endpoint.datacenter, - "city": location.city, - "country": location.country, - "region": location.region, - "latitude": location.latitude, - "longitude": location.longitude, - } + setattr( + zscaler_endpoints, + key, + cls( + ip_address=vpn_endpoint.ip_address.value, + datacenter=vpn_endpoint.datacenter, + city=location.city, + country=location.country, + region=location.region, + latitude=location.latitude, + longitude=location.longitude, + ), + ) return zscaler_endpoints diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/vlan_interfaces.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/vlan_interfaces.py index 6541380aa02..d07d1fa2fee 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/vlan_interfaces.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/vlan_interfaces.py @@ -13,6 +13,8 @@ from .utils import UtilsMixin if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + from . import AvdStructuredConfigNetworkServices @@ -35,8 +37,8 @@ def vlan_interfaces(self: AvdStructuredConfigNetworkServices) -> list | None: vlan_interfaces = [] for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: - for svi in vrf["svis"]: + for vrf in tenant.vrfs: + for svi in vrf.svis: vlan_interface = self._get_vlan_interface_config_for_svi(svi, vrf) append_if_not_duplicate( list_of_dicts=vlan_interfaces, @@ -67,7 +69,11 @@ def vlan_interfaces(self: AvdStructuredConfigNetworkServices) -> list | None: return None - def _get_vlan_interface_config_for_svi(self: AvdStructuredConfigNetworkServices, svi: dict, vrf: dict) -> dict: + def _get_vlan_interface_config_for_svi( + self: AvdStructuredConfigNetworkServices, + svi: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem, + vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem, + ) -> dict: def _check_virtual_router_mac_address(vlan_interface_config: dict, variables: list) -> None: """ Error if virtual router mac address is required but missing. @@ -78,49 +84,49 @@ def _check_virtual_router_mac_address(vlan_interface_config: dict, variables: li NOTE: SVI settings are also used for subinterfaces for uplink_type: 'lan'. So any changes here may also be needed in underlay.utils.UtilsMixin._get_l2_as_subint(). """ - if any(vlan_interface_config.get(var) for var in variables) and self.shared_utils.virtual_router_mac_address is None: + if any(vlan_interface_config.get(var) for var in variables) and self.shared_utils.node_config.virtual_router_mac_address is None: quoted_vars = [f"'{var}'" for var in variables] msg = f"'virtual_router_mac_address' must be set for node '{self.shared_utils.hostname}' when using {' or '.join(quoted_vars)} under 'svi'" raise AristaAvdInvalidInputsError(msg) - interface_name = f"Vlan{svi['id']}" + interface_name = f"Vlan{svi.id}" vlan_interface_config = { "name": interface_name, - "tenant": svi["tenant"], - "tags": svi.get("tags"), - "description": default(svi.get("description"), svi["name"]), - "shutdown": not (svi.get("enabled", False)), - "ip_address": svi.get("ip_address"), - "ipv6_address": svi.get("ipv6_address"), - "ipv6_enable": svi.get("ipv6_enable"), + "tenant": svi._tenant, + "tags": list(svi._get("tags", [])) or None, # Historic behavior is to not output the default ["all"] + "description": default(svi.description, svi.name), + "shutdown": not default(svi.enabled, False), # noqa: FBT003 + "ip_address": svi.ip_address, + "ipv6_address": svi.ipv6_address, + "ipv6_enable": svi.ipv6_enable, "access_group_in": get(self._svi_acls, f"{interface_name}.ipv4_acl_in.name"), "access_group_out": get(self._svi_acls, f"{interface_name}.ipv4_acl_out.name"), - "mtu": svi.get("mtu") if self.shared_utils.platform_settings_feature_support_per_interface_mtu else None, - "eos_cli": svi.get("raw_eos_cli"), - "struct_cfg": svi.get("structured_config"), + "mtu": svi.mtu if self.shared_utils.platform_settings.feature_support.per_interface_mtu else None, + "eos_cli": svi.raw_eos_cli, + "struct_cfg": svi.structured_config._as_dict(strip_values=()) or None, } # Only set VARP if ip_address is set if vlan_interface_config["ip_address"] is not None: - vlan_interface_config["ip_virtual_router_addresses"] = svi.get("ip_virtual_router_addresses") + vlan_interface_config["ip_virtual_router_addresses"] = svi.ip_virtual_router_addresses._as_list() or None _check_virtual_router_mac_address(vlan_interface_config, ["ip_virtual_router_addresses"]) # Only set Anycast GW if VARP is not set if vlan_interface_config.get("ip_virtual_router_addresses") is None: - vlan_interface_config["ip_address_virtual"] = svi.get("ip_address_virtual") - vlan_interface_config["ip_address_virtual_secondaries"] = svi.get("ip_address_virtual_secondaries") + vlan_interface_config["ip_address_virtual"] = svi.ip_address_virtual + vlan_interface_config["ip_address_virtual_secondaries"] = svi.ip_address_virtual_secondaries._as_list() or None _check_virtual_router_mac_address(vlan_interface_config, ["ip_address_virtual", "ip_address_virtual_secondaries"]) pim_config_ipv4 = {} - if default(get(svi, "evpn_l3_multicast.enabled"), get(vrf, "_evpn_l3_multicast_enabled")) is True: + if default(svi.evpn_l3_multicast.enabled, getattr(vrf, "_evpn_l3_multicast_enabled", False)) is True: if self.shared_utils.mlag: pim_config_ipv4["sparse_mode"] = True else: vlan_interface_config["ip_igmp"] = True if "ip_address_virtual" in vlan_interface_config: - if (vrf_diagnostic_loopback := get(vrf, "vtep_diagnostic.loopback")) is None: + if (vrf_diagnostic_loopback := vrf.vtep_diagnostic.loopback) is None: msg = ( - f"No vtep_diagnostic loopback defined on VRF '{vrf['name']}' in Tenant '{svi['tenant']}'." + f"No vtep_diagnostic loopback defined on VRF '{vrf.name}' in Tenant '{svi._tenant}'." "This is required when 'l3_multicast' is enabled on the VRF and ip_address_virtual is used on an SVI in that VRF." ) raise AristaAvdInvalidInputsError(msg) @@ -131,13 +137,13 @@ def _check_virtual_router_mac_address(vlan_interface_config: dict, variables: li # Only set VARPv6 if ipv6_address is set or ipv6_enable is set to true if vlan_interface_config["ipv6_address"] is not None or vlan_interface_config["ipv6_enable"]: - vlan_interface_config["ipv6_virtual_router_addresses"] = svi.get("ipv6_virtual_router_addresses") + vlan_interface_config["ipv6_virtual_router_addresses"] = svi.ipv6_virtual_router_addresses._as_list() or None _check_virtual_router_mac_address(vlan_interface_config, ["ipv6_virtual_router_addresses"]) # Only set Anycast v6 GW if VARPv6 is not set if vlan_interface_config.get("ipv6_virtual_router_addresses") is None: - if (ipv6_address_virtuals := svi.get("ipv6_address_virtuals")) is not None: - vlan_interface_config["ipv6_address_virtuals"] = ipv6_address_virtuals + if svi.ipv6_address_virtuals: + vlan_interface_config["ipv6_address_virtuals"] = svi.ipv6_address_virtuals._as_list() _check_virtual_router_mac_address(vlan_interface_config, ["ipv6_address_virtuals"]) @@ -145,52 +151,56 @@ def _check_virtual_router_mac_address(vlan_interface_config: dict, variables: li # If any anycast IPs are set, we also enable link-local IPv6 per best practice, unless specifically disabled with 'ipv6_enable: false' vlan_interface_config["ipv6_enable"] = get(vlan_interface_config, "ipv6_enable", default=True) - if vrf["name"] != "default": - vlan_interface_config["vrf"] = vrf["name"] + if vrf.name != "default": + vlan_interface_config["vrf"] = vrf.name # Adding IP helpers and OSPF via a common function also used for subinterfaces when uplink_type: lan self.shared_utils.get_additional_svi_config(vlan_interface_config, svi, vrf) return strip_empties_from_dict(vlan_interface_config) - def _get_vlan_interface_config_for_mlag_peering(self: AvdStructuredConfigNetworkServices, vrf: dict, vlan_id: int) -> dict: + def _get_vlan_interface_config_for_mlag_peering( + self: AvdStructuredConfigNetworkServices, vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem, vlan_id: int + ) -> dict: """Build full config for MLAG peering SVI for the given VRF.""" vlan_interface_config = { - "tenant": vrf["tenant"], + "tenant": vrf._tenant, "type": "underlay_peering", "shutdown": False, "description": self.shared_utils.interface_descriptions.mlag_peer_l3_vrf_svi( - InterfaceDescriptionData(shared_utils=self.shared_utils, interface=f"Vlan{vlan_id}", vrf=vrf["name"], vlan=vlan_id) + InterfaceDescriptionData(shared_utils=self.shared_utils, interface=f"Vlan{vlan_id}", vrf=vrf.name, vlan=vlan_id) ), - "vrf": vrf["name"], + "vrf": vrf.name, "mtu": self.shared_utils.p2p_uplinks_mtu, } vlan_interface_config.update(self._get_vlan_ip_config_for_mlag_peering(vrf)) return vlan_interface_config - def _get_vlan_ip_config_for_mlag_peering(self: AvdStructuredConfigNetworkServices, vrf: dict) -> dict: + def _get_vlan_ip_config_for_mlag_peering( + self: AvdStructuredConfigNetworkServices, vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem + ) -> dict: """ Build IP config for MLAG peering SVI for the given VRF. Called from _get_vlan_interface_config_for_mlag_peering and prefix_lists. """ - if self.shared_utils.underlay_rfc5549 and self.shared_utils.overlay_mlag_rfc5549: + if self.inputs.underlay_rfc5549 and self.inputs.overlay_mlag_rfc5549: return {"ipv6_enable": True} - if (mlag_ibgp_peering_ipv4_pool := vrf.get("mlag_ibgp_peering_ipv4_pool")) is not None: + if vrf.mlag_ibgp_peering_ipv4_pool: if self.shared_utils.mlag_role == "primary": return { "ip_address": ( - f"{self.shared_utils.ip_addressing.mlag_ibgp_peering_ip_primary(mlag_ibgp_peering_ipv4_pool)}/" - f"{self.shared_utils.fabric_ip_addressing_mlag_ipv4_prefix_length}" + f"{self.shared_utils.ip_addressing.mlag_ibgp_peering_ip_primary(vrf.mlag_ibgp_peering_ipv4_pool)}/" + f"{self.inputs.fabric_ip_addressing.mlag.ipv4_prefix_length}" ) } return { "ip_address": ( - f"{self.shared_utils.ip_addressing.mlag_ibgp_peering_ip_secondary(mlag_ibgp_peering_ipv4_pool)}/" - f"{self.shared_utils.fabric_ip_addressing_mlag_ipv4_prefix_length}" + f"{self.shared_utils.ip_addressing.mlag_ibgp_peering_ip_secondary(vrf.mlag_ibgp_peering_ipv4_pool)}/" + f"{self.inputs.fabric_ip_addressing.mlag.ipv4_prefix_length}" ) } - return {"ip_address": f"{self.shared_utils.mlag_ibgp_ip}/{self.shared_utils.fabric_ip_addressing_mlag_ipv4_prefix_length}"} + return {"ip_address": f"{self.shared_utils.mlag_ibgp_ip}/{self.inputs.fabric_ip_addressing.mlag.ipv4_prefix_length}"} diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/vlans.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/vlans.py index bf5eca7445d..9807dba8559 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/vlans.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/vlans.py @@ -12,6 +12,8 @@ from .utils import UtilsMixin if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + from . import AvdStructuredConfigNetworkServices @@ -37,14 +39,14 @@ def vlans(self: AvdStructuredConfigNetworkServices) -> list | None: vlans = [] for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: - for svi in vrf["svis"]: + for vrf in tenant.vrfs: + for svi in vrf.svis: vlan = self._get_vlan_config(svi) append_if_not_duplicate( list_of_dicts=vlans, primary_key="id", new_dict=vlan, - context=f"SVIs in VRF '{vrf['name']}'", + context=f"SVIs in VRF '{vrf.name}'", context_keys=["id", "name", "tenant"], ignore_keys={"tenant"}, ) @@ -57,22 +59,22 @@ def vlans(self: AvdStructuredConfigNetworkServices) -> list | None: vlan = { "id": vlan_id, "name": AvdStringFormatter().format( - self.shared_utils.mlag_peer_l3_vrf_vlan_name, mlag_peer=self.shared_utils.mlag_peer, vlan=vlan_id, vrf=vrf["name"] + self.inputs.mlag_peer_l3_vrf_vlan_name, mlag_peer=self.shared_utils.mlag_peer, vlan=vlan_id, vrf=vrf.name ), - "trunk_groups": [self._trunk_groups_mlag_l3_name], - "tenant": tenant["name"], + "trunk_groups": [self.inputs.trunk_groups.mlag_l3.name], + "tenant": tenant.name, } append_if_not_duplicate( list_of_dicts=vlans, primary_key="id", new_dict=vlan, - context=f"MLAG Peering VLAN in VRF '{vrf['name']}' (check for duplicate VRF VNI/ID)", + context=f"MLAG Peering VLAN in VRF '{vrf.name}' (check for duplicate VRF VNI/ID)", context_keys=["id", "name", "tenant"], ignore_keys={"tenant"}, ) # L2 Vlans per Tenant - for l2vlan in tenant["l2vlans"]: + for l2vlan in tenant.l2vlans: vlan = self._get_vlan_config(l2vlan) append_if_not_duplicate( list_of_dicts=vlans, @@ -88,25 +90,29 @@ def vlans(self: AvdStructuredConfigNetworkServices) -> list | None: return None - def _get_vlan_config(self: AvdStructuredConfigNetworkServices, vlan: dict) -> dict: + def _get_vlan_config( + self: AvdStructuredConfigNetworkServices, + vlan: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem + | EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.L2vlansItem, + ) -> dict: """ Return structured config for one given vlan. Can be used for svis and l2vlans """ vlans_vlan = { - "id": int(vlan["id"]), - "name": vlan["name"], - "tenant": vlan["tenant"], + "id": vlan.id, + "name": vlan.name, + "tenant": vlan._tenant, } - if self.shared_utils.enable_trunk_groups: - trunk_groups = vlan.get("trunk_groups", []) + if self.inputs.enable_trunk_groups: + trunk_groups = vlan.trunk_groups if self.shared_utils.only_local_vlan_trunk_groups: trunk_groups = list(self._local_endpoint_trunk_groups.intersection(trunk_groups)) if self.shared_utils.mlag: - trunk_groups.append(self._trunk_groups_mlag_name) + trunk_groups.append(self.inputs.trunk_groups.mlag.name) if self.shared_utils.uplink_type == "port-channel": - trunk_groups.append(self._trunk_groups_uplink_name) + trunk_groups.append(self.inputs.trunk_groups.uplink.name) vlans_vlan["trunk_groups"] = natural_sort(trunk_groups) return vlans_vlan diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/vrfs.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/vrfs.py index f139620a401..6ff30ff43f7 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/vrfs.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/vrfs.py @@ -11,6 +11,8 @@ from .utils import UtilsMixin if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + from . import AvdStructuredConfigNetworkServices @@ -36,18 +38,18 @@ def vrfs(self: AvdStructuredConfigNetworkServices) -> list | None: vrfs = [] for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: - vrf_name = vrf["name"] + for vrf in tenant.vrfs: + vrf_name = vrf.name if vrf_name == "default": continue new_vrf = { "name": vrf_name, - "tenant": tenant["name"], + "tenant": tenant.name, } # MLAG IBGP Peering VLANs per VRF - if self.shared_utils.overlay_mlag_rfc5549 and self._mlag_ibgp_peering_enabled(vrf, tenant): + if self.inputs.overlay_mlag_rfc5549 and self._mlag_ibgp_peering_enabled(vrf, tenant): new_vrf["ip_routing_ipv6_interfaces"] = True new_vrf["ipv6_routing"] = True else: @@ -56,8 +58,8 @@ def vrfs(self: AvdStructuredConfigNetworkServices) -> list | None: if self._has_ipv6(vrf): new_vrf["ipv6_routing"] = True - if "description" in vrf: - new_vrf["description"] = vrf["description"] + if vrf.description: + new_vrf["description"] = vrf.description append_if_not_duplicate( list_of_dicts=vrfs, @@ -73,17 +75,10 @@ def vrfs(self: AvdStructuredConfigNetworkServices) -> list | None: return None - def _has_ipv6(self: AvdStructuredConfigNetworkServices, vrf: dict) -> bool: + def _has_ipv6(self: AvdStructuredConfigNetworkServices, vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem) -> bool: """ Return bool if IPv6 is configured in the given VRF. Expects a VRF definition coming from filtered_tenants, where all keys have been set and filtered """ - for svi in vrf["svis"]: - if len(svi.get("ipv6_address_virtuals", [])) > 0: - return True - - if svi.get("ipv6_address") is not None: - return True - - return False + return any(svi.ipv6_address or svi.ipv6_address_virtuals for svi in vrf.svis) diff --git a/python-avd/pyavd/_eos_designs/structured_config/network_services/vxlan_interface.py b/python-avd/pyavd/_eos_designs/structured_config/network_services/vxlan_interface.py index 1c0e4b53d7e..f415b5792ed 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/network_services/vxlan_interface.py +++ b/python-avd/pyavd/_eos_designs/structured_config/network_services/vxlan_interface.py @@ -4,15 +4,17 @@ from __future__ import annotations from functools import cached_property -from typing import TYPE_CHECKING, NoReturn +from typing import TYPE_CHECKING -from pyavd._errors import AristaAvdError, AristaAvdInvalidInputsError -from pyavd._utils import append_if_not_duplicate, default, get, get_item, unique +from pyavd._errors import AristaAvdInvalidInputsError +from pyavd._utils import append_if_not_duplicate, default, unique from pyavd.j2filters import natural_sort, range_expand from .utils import UtilsMixin if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + from . import AvdStructuredConfigNetworkServices @@ -49,25 +51,25 @@ def vxlan_interface(self: AvdStructuredConfigNetworkServices) -> dict | None: if self.shared_utils.mlag_l3 and self.shared_utils.network_services_l3 and self.shared_utils.overlay_evpn: vxlan["virtual_router_encapsulation_mac_address"] = "mlag-system-id" - if self.shared_utils.overlay_her and self._overlay_her_flood_list_per_vni is False and (common := self._overlay_her_flood_lists.get("common")): + if self.shared_utils.overlay_her and not self.inputs.overlay_her_flood_list_per_vni and (common := self._overlay_her_flood_lists.get("common")): vxlan["flood_vteps"] = natural_sort(unique(common)) if self.shared_utils.overlay_cvx: vxlan["controller_client"] = {"enabled": True} - vlans = [] - vrfs = [] + vlans: list[dict] = [] + vrfs: list[dict] = [] # vnis is a list of dicts only used for duplication checks across multiple types of objects all having "vni" as a key. - vnis = [] + vnis: list[dict] = [] for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: + for vrf in tenant.vrfs: self._get_vxlan_interface_config_for_vrf(vrf, tenant, vrfs, vlans, vnis) if not self.shared_utils.network_services_l2: continue - for l2vlan in tenant["l2vlans"]: + for l2vlan in tenant.l2vlans: if vlan := self._get_vxlan_interface_config_for_vlan(l2vlan, tenant): # Duplicate check is not done on the actual list of vlans, but instead on our local "vnis" list. # This is necessary to find duplicate VNIs across multiple object types. @@ -92,7 +94,7 @@ def vxlan_interface(self: AvdStructuredConfigNetworkServices) -> dict | None: for vrf in self._filtered_wan_vrfs: # Duplicate check is not done on the actual list of vlans, but instead on our local "vnis" list. # This is necessary to find duplicate VNIs across multiple object types. - vrf_data = {"name": vrf["name"], "vni": vrf["wan_vni"]} + vrf_data = {"name": vrf.name, "vni": vrf.wan_vni} append_if_not_duplicate( list_of_dicts=vnis, primary_key="vni", @@ -122,10 +124,17 @@ def vxlan_interface(self: AvdStructuredConfigNetworkServices) -> dict | None: }, } - def _get_vxlan_interface_config_for_vrf(self: AvdStructuredConfigNetworkServices, vrf: dict, tenant: dict, vrfs: list, vlans: list, vnis: list) -> None: + def _get_vxlan_interface_config_for_vrf( + self: AvdStructuredConfigNetworkServices, + vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem, + tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem, + vrfs: list[dict], + vlans: list[dict], + vnis: list[dict], + ) -> None: """In place updates of the vlans, vnis and vrfs list.""" if self.shared_utils.network_services_l2: - for svi in vrf["svis"]: + for svi in vrf.svis: if vlan := self._get_vxlan_interface_config_for_vlan(svi, tenant): # Duplicate check is not done on the actual list of vlans, but instead on our local "vnis" list. # This is necessary to find duplicate VNIs across multiple object types. @@ -146,121 +155,111 @@ def _get_vxlan_interface_config_for_vrf(self: AvdStructuredConfigNetworkServices ) if self.shared_utils.network_services_l3 and self.shared_utils.overlay_evpn_vxlan: - vrf_name = vrf["name"] + vrf_name = vrf.name # Only configure VNI for VRF if the VRF is EVPN enabled - if "evpn" not in vrf.get("address_families", ["evpn"]): + if "evpn" not in vrf.address_families: return if self.shared_utils.is_wan_router: # Every VRF with EVPN on a WAN router must have a wan_vni defined. - error_message = ( - f"The VRF '{vrf_name}' does not have a `wan_vni` defined under 'wan_virtual_topologies'. " - "If this VRF was not intended to be extended over the WAN, but still required to be configured on the WAN router, " - "set 'address_families: []' under the VRF definition. If this VRF was not intended to be configured on the WAN router, " - "use the VRF filter 'deny_vrfs' under the node settings." - ) - wan_vrf = get_item(self._filtered_wan_vrfs, "name", vrf_name, required=True, custom_error_msg=error_message) - vni = get(wan_vrf, "wan_vni", required=True, custom_error_msg=error_message) + if vrf_name not in self._filtered_wan_vrfs: + msg = ( + f"The VRF '{vrf_name}' does not have a `wan_vni` defined under 'wan_virtual_topologies'. " + "If this VRF was not intended to be extended over the WAN, but still required to be configured on the WAN router, " + "set 'address_families: []' under the VRF definition. If this VRF was not intended to be configured on the WAN router, " + "use the VRF filter 'deny_vrfs' under the node settings." + ) + raise AristaAvdInvalidInputsError(msg) + vni = self._filtered_wan_vrfs[vrf_name].wan_vni else: - vni = default( - vrf.get("vrf_vni"), - vrf.get("vrf_id"), - ) + vni = default(vrf.vrf_vni, vrf.vrf_id) - # NOTE: this can never be None here, it would be caught previously in the code - vrf_id = default( - vrf.get("vrf_id"), - vrf.get("vrf_vni"), - ) - if vni is not None: + if vni is None: # Silently ignore if we cannot set a VNI # This is legacy behavior so we will leave stricter enforcement to the schema - vrf_data = {"name": vrf_name, "vni": vni} - - if get(vrf, "_evpn_l3_multicast_enabled"): - if vrf_multicast_group := get(vrf, "_evpn_l3_multicast_group_ip"): - vrf_data["multicast_group"] = vrf_multicast_group - else: - underlay_l3_multicast_group_ipv4_pool = get( - tenant, - "evpn_l3_multicast.evpn_underlay_l3_multicast_group_ipv4_pool", - required=True, - custom_error_msg=f"'evpn_l3_multicast.evpn_underlay_l3_multicast_group_ipv4_pool' for Tenant: {tenant['name']} is required.", - ) - underlay_l3_mcast_group_ipv4_pool_offset = get(tenant, "evpn_l3_multicast.evpn_underlay_l3_multicast_group_ipv4_pool_offset", default=0) - vrf_data["multicast_group"] = self.shared_utils.ip_addressing.evpn_underlay_l3_multicast_group( - underlay_l3_multicast_group_ipv4_pool, - vni, - vrf_id, - underlay_l3_mcast_group_ipv4_pool_offset, - ) + return - # Duplicate check is not done on the actual list of vlans, but instead on our local "vnis" list. - # This is necessary to find duplicate VNIs across multiple object types. - append_if_not_duplicate( - list_of_dicts=vnis, - primary_key="vni", - new_dict=vrf_data, - context="VXLAN VNIs for VRFs", - context_keys=["id", "name", "vni"], - ) - # Here we append to the actual list of VRFs, so duplication check is on the VRF here. - append_if_not_duplicate( - list_of_dicts=vrfs, - primary_key="name", - new_dict=vrf_data, - context="VXLAN VNIs for VRFs", - context_keys=["name", "vni"], - ) + # NOTE: this can never be None here, it would be caught previously in the code + vrf_id: int = default(vrf.vrf_id, vrf.vrf_vni) + + vrf_data = {"name": vrf_name, "vni": vni} + + if getattr(vrf, "_evpn_l3_multicast_enabled", False): + if vrf_multicast_group := getattr(vrf, "_evpn_l3_multicast_group_ip", None): + vrf_data["multicast_group"] = vrf_multicast_group + else: + if not tenant.evpn_l3_multicast.evpn_underlay_l3_multicast_group_ipv4_pool: + msg = f"'evpn_l3_multicast.evpn_underlay_l3_multicast_group_ipv4_pool' for Tenant: {tenant.name} is required." + raise AristaAvdInvalidInputsError(msg) + + vrf_data["multicast_group"] = self.shared_utils.ip_addressing.evpn_underlay_l3_multicast_group( + tenant.evpn_l3_multicast.evpn_underlay_l3_multicast_group_ipv4_pool, + vni, + vrf_id, + tenant.evpn_l3_multicast.evpn_underlay_l3_multicast_group_ipv4_pool_offset, + ) + + # Duplicate check is not done on the actual list of vlans, but instead on our local "vnis" list. + # This is necessary to find duplicate VNIs across multiple object types. + append_if_not_duplicate( + list_of_dicts=vnis, + primary_key="vni", + new_dict=vrf_data, + context="VXLAN VNIs for VRFs", + context_keys=["id", "name", "vni"], + ) + # Here we append to the actual list of VRFs, so duplication check is on the VRF here. + append_if_not_duplicate( + list_of_dicts=vrfs, + primary_key="name", + new_dict=vrf_data, + context="VXLAN VNIs for VRFs", + context_keys=["name", "vni"], + ) - def _get_vxlan_interface_config_for_vlan(self: AvdStructuredConfigNetworkServices, vlan: dict, tenant: dict) -> dict: + def _get_vxlan_interface_config_for_vlan( + self: AvdStructuredConfigNetworkServices, + vlan: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem + | EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.L2vlansItem, + tenant: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem, + ) -> dict: """ vxlan_interface logic for one vlan. Can be used for both svis and l2vlans """ - if vlan.get("vxlan") is False: + if not vlan.vxlan: return {} - vlan_id = int(vlan["id"]) - vxlan_interface_vlan = {"id": vlan_id} - if (vni_override := vlan.get("vni_override")) is not None: - vxlan_interface_vlan["vni"] = int(vni_override) + vxlan_interface_vlan = {"id": vlan.id} + if vlan.vni_override: + vxlan_interface_vlan["vni"] = vlan.vni_override else: - mac_vrf_vni_base = int( - get(tenant, "mac_vrf_vni_base", required=True, custom_error_msg=f"'mac_vrf_vni_base' for Tenant: {tenant['name']} is required.") - ) - vxlan_interface_vlan["vni"] = mac_vrf_vni_base + vlan_id + if tenant.mac_vrf_vni_base is None: + msg = f"'mac_vrf_vni_base' for Tenant: {tenant.name} is required." + raise AristaAvdInvalidInputsError(msg) + vxlan_interface_vlan["vni"] = tenant.mac_vrf_vni_base + vlan.id - vlan_evpn_l2_multicast_enabled = ( - default(get(vlan, "evpn_l2_multicast.enabled"), get(tenant, "evpn_l2_multicast.enabled")) and self.shared_utils.evpn_multicast is True - ) + vlan_evpn_l2_multicast_enabled = bool(default(vlan.evpn_l2_multicast.enabled, tenant.evpn_l2_multicast.enabled)) and self.shared_utils.evpn_multicast if vlan_evpn_l2_multicast_enabled is True: - underlay_l2_multicast_group_ipv4_pool = get( - tenant, - "evpn_l2_multicast.underlay_l2_multicast_group_ipv4_pool", - required=True, - custom_error_msg=f"'evpn_l2_multicast.underlay_l2_multicast_group_ipv4_pool' for Tenant: {tenant['name']} is required.", - ) - underlay_l2_multicast_group_ipv4_pool_offset = get(tenant, "evpn_l2_multicast.underlay_l2_multicast_group_ipv4_pool_offset", default=0) + if not tenant.evpn_l2_multicast.underlay_l2_multicast_group_ipv4_pool: + msg = f"'evpn_l2_multicast.underlay_l2_multicast_group_ipv4_pool' for Tenant: {tenant.name} is required." + raise AristaAvdInvalidInputsError(msg) + vxlan_interface_vlan["multicast_group"] = self.shared_utils.ip_addressing.evpn_underlay_l2_multicast_group( - underlay_l2_multicast_group_ipv4_pool, - vlan_id, - underlay_l2_multicast_group_ipv4_pool_offset, + tenant.evpn_l2_multicast.underlay_l2_multicast_group_ipv4_pool, + vlan.id, + tenant.evpn_l2_multicast.underlay_l2_multicast_group_ipv4_pool_offset, ) - if self.shared_utils.overlay_her and self._overlay_her_flood_list_per_vni and (vlan_id_entry := self._overlay_her_flood_lists.get(vlan_id)): + if self.shared_utils.overlay_her and self.inputs.overlay_her_flood_list_per_vni and (vlan_id_entry := self._overlay_her_flood_lists.get(vlan.id)): vxlan_interface_vlan["flood_vteps"] = natural_sort(unique(vlan_id_entry)) return vxlan_interface_vlan @cached_property - def _overlay_her_flood_list_per_vni(self: AvdStructuredConfigNetworkServices) -> bool: - return get(self._hostvars, "overlay_her_flood_list_per_vni") is True - - @cached_property - def _overlay_her_flood_lists(self: AvdStructuredConfigNetworkServices) -> dict[list]: + def _overlay_her_flood_lists(self: AvdStructuredConfigNetworkServices) -> dict[str | int, list]: """ Returns a dict with HER Flood Lists. @@ -277,9 +276,9 @@ def _overlay_her_flood_lists(self: AvdStructuredConfigNetworkServices) -> dict[l - Otherwise an error will be raised """ overlay_her_flood_lists = {} - overlay_her_flood_list_scope = get(self._hostvars, "overlay_her_flood_list_scope") + overlay_her_flood_list_scope = self.inputs.overlay_her_flood_list_scope - if overlay_her_flood_list_scope == "dc" and self.shared_utils.dc_name is None: + if overlay_her_flood_list_scope == "dc" and self.inputs.dc_name is None: msg = "'dc_name' is required with 'overlay_her_flood_list_scope: dc'" raise AristaAvdInvalidInputsError(msg) @@ -289,13 +288,13 @@ def _overlay_her_flood_lists(self: AvdStructuredConfigNetworkServices) -> dict[l peer_facts = self.shared_utils.get_peer_facts(peer, required=True) - if overlay_her_flood_list_scope == "dc" and peer_facts.get("dc_name") != self.shared_utils.dc_name: + if overlay_her_flood_list_scope == "dc" and peer_facts.get("dc_name") != self.inputs.dc_name: continue if (vtep_ip := peer_facts.get("vtep_ip")) is None: continue - if not self._overlay_her_flood_list_per_vni: + if not self.inputs.overlay_her_flood_list_per_vni: # Use common flood list overlay_her_flood_lists.setdefault("common", []).append(vtep_ip) continue @@ -308,13 +307,6 @@ def _overlay_her_flood_lists(self: AvdStructuredConfigNetworkServices) -> dict[l return overlay_her_flood_lists - def _raise_duplicate_vni_error(self: AvdStructuredConfigNetworkServices, vni: int, context: str, tenant: str, duplicate_vni_tenant: str) -> NoReturn: - msg = f"Duplicate VXLAN VNI '{vni}' found in Tenant(s) '{tenant}' during configuration of {context}." - if duplicate_vni_tenant != tenant: - msg = f"{msg} Other VNI is in Tenant(s) '{duplicate_vni_tenant}'." - - raise AristaAvdError(msg) - @cached_property def _multi_vtep(self: AvdStructuredConfigNetworkServices) -> bool: return self.shared_utils.mlag is True and self.shared_utils.evpn_multicast is True diff --git a/python-avd/pyavd/_eos_designs/structured_config/overlay/cvx.py b/python-avd/pyavd/_eos_designs/structured_config/overlay/cvx.py index 3f5db9fcde7..6ef2d3b5154 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/overlay/cvx.py +++ b/python-avd/pyavd/_eos_designs/structured_config/overlay/cvx.py @@ -27,12 +27,11 @@ def cvx(self: AvdStructuredConfigOverlay) -> dict | None: if not self.shared_utils.overlay_cvx: return None - overlay_cvx_servers = get(self._hostvars, "overlay_cvx_servers", default=[]) - if self.shared_utils.hostname not in overlay_cvx_servers: + if self.shared_utils.hostname not in self.inputs.overlay_cvx_servers: return None peer_hosts = [] - for overlay_cvx_server in overlay_cvx_servers: + for overlay_cvx_server in self.inputs.overlay_cvx_servers: if overlay_cvx_server == self.shared_utils.hostname: continue diff --git a/python-avd/pyavd/_eos_designs/structured_config/overlay/ip_security.py b/python-avd/pyavd/_eos_designs/structured_config/overlay/ip_security.py index 31e289b7669..ed3220bd09a 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/overlay/ip_security.py +++ b/python-avd/pyavd/_eos_designs/structured_config/overlay/ip_security.py @@ -6,6 +6,7 @@ from functools import cached_property from typing import TYPE_CHECKING +from pyavd._errors import AristaAvdMissingVariableError from pyavd._utils import get, strip_null_from_data from .utils import UtilsMixin @@ -34,15 +35,19 @@ def ip_security(self: AvdStructuredConfigOverlay) -> dict | None: if not self.shared_utils.is_wan_router: return None - wan_ipsec_profiles = get(self._hostvars, "wan_ipsec_profiles", required=True) + if not self.inputs.wan_ipsec_profiles: + msg = "wan_ipsec_profiles" + raise AristaAvdMissingVariableError(msg) + if not self.inputs.wan_ipsec_profiles.control_plane: + msg = "wan_ipsec_profiles.control_plane" + raise AristaAvdMissingVariableError(msg) # Structure initialization ip_security = {"ike_policies": [], "sa_policies": [], "profiles": []} - if self.shared_utils.is_wan_client and (data_plane := get(wan_ipsec_profiles, "data_plane")) is not None: - self._append_data_plane(ip_security, data_plane) - control_plane = get(wan_ipsec_profiles, "control_plane", required=True) - self._append_control_plane(ip_security, control_plane) + if self.shared_utils.is_wan_client and (data_plane := self.inputs.wan_ipsec_profiles.data_plane): + self._append_data_plane(ip_security, data_plane._as_dict()) + self._append_control_plane(ip_security, self.inputs.wan_ipsec_profiles.control_plane._as_dict()) return strip_null_from_data(ip_security) diff --git a/python-avd/pyavd/_eos_designs/structured_config/overlay/management_cvx.py b/python-avd/pyavd/_eos_designs/structured_config/overlay/management_cvx.py index e196648c977..a529da4a84f 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/overlay/management_cvx.py +++ b/python-avd/pyavd/_eos_designs/structured_config/overlay/management_cvx.py @@ -6,6 +6,7 @@ from functools import cached_property from typing import TYPE_CHECKING +from pyavd._errors import AristaAvdMissingVariableError from pyavd._utils import get, get_ip_from_ip_prefix from .utils import UtilsMixin @@ -26,9 +27,12 @@ def management_cvx(self: AvdStructuredConfigOverlay) -> dict | None: if not (self.shared_utils.overlay_cvx and self.shared_utils.overlay_vtep): return None + if not self.inputs.overlay_cvx_servers: + msg = "overlay_cvx_servers" + raise AristaAvdMissingVariableError(msg) + server_hosts = [] - overlay_cvx_servers = get(self._hostvars, "overlay_cvx_servers", required=True) - for overlay_cvx_server in overlay_cvx_servers: + for overlay_cvx_server in self.inputs.overlay_cvx_servers: peer_switch_facts = self.shared_utils.get_peer_facts(overlay_cvx_server, required=True) cvx_server_ip = get(peer_switch_facts, "mgmt_ip", required=True, custom_error_msg=f"'mgmt_ip' for CVX Server {overlay_cvx_server} is required.") server_hosts.append(get_ip_from_ip_prefix(cvx_server_ip)) diff --git a/python-avd/pyavd/_eos_designs/structured_config/overlay/route_maps.py b/python-avd/pyavd/_eos_designs/structured_config/overlay/route_maps.py index 786a6544e60..463734cc0d2 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/overlay/route_maps.py +++ b/python-avd/pyavd/_eos_designs/structured_config/overlay/route_maps.py @@ -30,8 +30,8 @@ def route_maps(self: AvdStructuredConfigOverlay) -> list | None: route_maps = [] if self.shared_utils.overlay_routing_protocol == "ebgp": - if self.shared_utils.evpn_prevent_readvertise_to_server is True: - remote_asns = natural_sort({rs_dict.get("bgp_as") for route_server, rs_dict in self._evpn_route_servers.items()}) + if self.inputs.evpn_prevent_readvertise_to_server: + remote_asns = natural_sort({rs_dict.get("bgp_as") for rs_dict in self._evpn_route_servers.values()}) for remote_asn in remote_asns: route_map_name = f"RM-EVPN-FILTER-AS{remote_asn}" route_maps.append( diff --git a/python-avd/pyavd/_eos_designs/structured_config/overlay/router_adaptive_virtual_topology.py b/python-avd/pyavd/_eos_designs/structured_config/overlay/router_adaptive_virtual_topology.py index 9d712f7272c..44d88ecbe17 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/overlay/router_adaptive_virtual_topology.py +++ b/python-avd/pyavd/_eos_designs/structured_config/overlay/router_adaptive_virtual_topology.py @@ -6,6 +6,8 @@ from functools import cached_property from typing import TYPE_CHECKING +from pyavd._errors import AristaAvdInvalidInputsError + from .utils import UtilsMixin if TYPE_CHECKING: @@ -29,16 +31,26 @@ def router_adaptive_virtual_topology(self: AvdStructuredConfigOverlay) -> dict | if self.shared_utils.is_cv_pathfinder_server: return {"topology_role": "pathfinder"} + if self.shared_utils.wan_region is None: + # Should never happen but just in case. + msg = "Could not find 'cv_pathfinder_region' so it is not possible to generate config for router_adaptive_virtual_topology." + raise AristaAvdInvalidInputsError(msg) + + if self.shared_utils.wan_site is None: + # Should never happen but just in case. + msg = "Could not find 'cv_pathfinder_site' so it is not possible to generate config for router_adaptive_virtual_topology." + raise AristaAvdInvalidInputsError(msg) + # Edge or Transit return { "topology_role": self.shared_utils.cv_pathfinder_role, "region": { - "name": self.shared_utils.wan_region["name"], - "id": self.shared_utils.wan_region["id"], + "name": self.shared_utils.wan_region.name, + "id": self.shared_utils.wan_region.id, }, "zone": self.shared_utils.wan_zone, "site": { - "name": self.shared_utils.wan_site["name"], - "id": self.shared_utils.wan_site["id"], + "name": self.shared_utils.wan_site.name, + "id": self.shared_utils.wan_site.id, }, } diff --git a/python-avd/pyavd/_eos_designs/structured_config/overlay/router_bfd.py b/python-avd/pyavd/_eos_designs/structured_config/overlay/router_bfd.py index 45ab29b62cb..a1814245196 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/overlay/router_bfd.py +++ b/python-avd/pyavd/_eos_designs/structured_config/overlay/router_bfd.py @@ -6,8 +6,6 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import strip_empties_from_dict - from .utils import UtilsMixin if TYPE_CHECKING: @@ -24,10 +22,7 @@ class RouterBfdMixin(UtilsMixin): @cached_property def router_bfd(self: AvdStructuredConfigOverlay) -> dict | None: """Return structured config for router_bfd.""" - if self.shared_utils.bfd_multihop is None: - return None - if self.shared_utils.overlay_cvx: return None - return strip_empties_from_dict({"multihop": self.shared_utils.bfd_multihop}) + return {"multihop": self.inputs.bfd_multihop._as_dict()} diff --git a/python-avd/pyavd/_eos_designs/structured_config/overlay/router_bgp.py b/python-avd/pyavd/_eos_designs/structured_config/overlay/router_bgp.py index 73dfc735135..54196e460d3 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/overlay/router_bgp.py +++ b/python-avd/pyavd/_eos_designs/structured_config/overlay/router_bgp.py @@ -8,12 +8,14 @@ from typing import TYPE_CHECKING from pyavd._errors import AristaAvdError -from pyavd._utils import AvdStringFormatter, default, get, strip_empties_from_dict +from pyavd._utils import AvdStringFormatter, default, strip_empties_from_dict from pyavd.j2filters import natural_sort from .utils import UtilsMixin if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + from . import AvdStructuredConfigOverlay @@ -53,7 +55,7 @@ def _bgp_cluster_id(self: AvdStructuredConfigOverlay) -> str | None: if self.shared_utils.overlay_routing_protocol == "ibgp" and ( self.shared_utils.evpn_role == "server" or self.shared_utils.mpls_overlay_role == "server" ): - return get(self.shared_utils.switch_data_combined, "bgp_cluster_id", default=self.shared_utils.router_id) + return default(self.shared_utils.node_config.bgp_cluster_id, self.shared_utils.router_id) return None def _bgp_listen_ranges(self: AvdStructuredConfigOverlay) -> list | None: @@ -64,7 +66,7 @@ def _bgp_listen_ranges(self: AvdStructuredConfigOverlay) -> list | None: return [ { "prefix": prefix, - "peer_group": self._get_peer_group_name("wan_overlay_peers"), + "peer_group": self.inputs.bgp_peer_groups.wan_overlay_peers.name, "remote_as": self.shared_utils.bgp_as, } for prefix in self.shared_utils.wan_listen_ranges @@ -77,15 +79,16 @@ def _generate_base_peer_group( maximum_routes: int = 0, update_source: str = "Loopback0", ) -> dict: + peer_group = getattr(self.inputs.bgp_peer_groups, pg_name) return { - "name": self.shared_utils.bgp_peer_groups[pg_name]["name"], + "name": peer_group.name, "type": pg_type, "update_source": update_source, - "bfd": self.shared_utils.bgp_peer_groups[pg_name]["bfd"], - "password": self.shared_utils.bgp_peer_groups[pg_name]["password"], + "bfd": peer_group.bfd, + "password": peer_group.password, "send_community": "all", "maximum_routes": maximum_routes, - "struct_cfg": self.shared_utils.bgp_peer_groups[pg_name]["structured_config"], + "struct_cfg": peer_group.structured_config._as_dict(strip_values=()) or None, } def _peer_groups(self: AvdStructuredConfigOverlay) -> list | None: @@ -95,7 +98,7 @@ def _peer_groups(self: AvdStructuredConfigOverlay) -> list | None: # EVPN OVERLAY peer group ebgp_peer_group = { **self._generate_base_peer_group("evpn", "evpn_overlay_peers"), - "ebgp_multihop": self.shared_utils.evpn_ebgp_multihop, + "ebgp_multihop": self.inputs.evpn_ebgp_multihop, } if self.shared_utils.evpn_role == "server": @@ -103,11 +106,11 @@ def _peer_groups(self: AvdStructuredConfigOverlay) -> list | None: peer_groups.append(ebgp_peer_group) - if self.shared_utils.evpn_gateway_vxlan_l2 is True or self.shared_utils.evpn_gateway_vxlan_l3 is True: + if self.shared_utils.node_config.evpn_gateway.evpn_l2.enabled or self.shared_utils.node_config.evpn_gateway.evpn_l3.enabled: peer_groups.append( { **self._generate_base_peer_group("evpn", "evpn_overlay_core"), - "ebgp_multihop": self.shared_utils.evpn_ebgp_gateway_multihop, + "ebgp_multihop": self.inputs.evpn_ebgp_gateway_multihop, }, ) @@ -128,10 +131,10 @@ def _peer_groups(self: AvdStructuredConfigOverlay) -> list | None: peer_group_config = {"remote_as": self.shared_utils.bgp_as} if self.shared_utils.is_wan_router: # WAN OVERLAY peer group - peer_group_config["ttl_maximum_hops"] = self.shared_utils.bgp_peer_groups["wan_overlay_peers"]["ttl_maximum_hops"] + peer_group_config["ttl_maximum_hops"] = self.inputs.bgp_peer_groups.wan_overlay_peers.ttl_maximum_hops if self.shared_utils.is_wan_server: peer_group_config["route_reflector_client"] = True - peer_group_config["bfd_timers"] = get(self.shared_utils.bgp_peer_groups["wan_overlay_peers"], "bfd_timers") + peer_group_config["bfd_timers"] = self.inputs.bgp_peer_groups.wan_overlay_peers.bfd_timers._as_dict(include_default_values=True) peer_groups.append( { **self._generate_base_peer_group("wan", "wan_overlay_peers", update_source=self.shared_utils.vtep_loopback), @@ -158,8 +161,8 @@ def _peer_groups(self: AvdStructuredConfigOverlay) -> list | None: wan_rr_overlay_peer_group.update( { "remote_as": self.shared_utils.bgp_as, - "ttl_maximum_hops": self.shared_utils.bgp_peer_groups["wan_rr_overlay_peers"]["ttl_maximum_hops"], - "bfd_timers": get(self.shared_utils.bgp_peer_groups["wan_rr_overlay_peers"], "bfd_timers"), + "ttl_maximum_hops": self.inputs.bgp_peer_groups.wan_rr_overlay_peers.ttl_maximum_hops, + "bfd_timers": self.inputs.bgp_peer_groups.wan_rr_overlay_peers.bfd_timers._as_dict(include_default_values=True), "route_reflector_client": True, }, ) @@ -170,8 +173,8 @@ def _peer_groups(self: AvdStructuredConfigOverlay) -> list | None: peer_groups.append( { **self._generate_base_peer_group("mpls", "ipvpn_gateway_peers"), - "local_as": self._ipvpn_gateway_local_as, - "maximum_routes": get(self.shared_utils.switch_data_combined, "ipvpn_gateway.maximum_routes", default=0), + "local_as": self.shared_utils.node_config.ipvpn_gateway.local_as, + "maximum_routes": self.shared_utils.node_config.ipvpn_gateway.maximum_routes, }, ) @@ -182,36 +185,32 @@ def _address_family_ipv4(self: AvdStructuredConfigOverlay) -> dict: peer_groups = [] if self.shared_utils.is_wan_router: - peer_groups.append({"name": self._get_peer_group_name("wan_overlay_peers"), "activate": False}) + peer_groups.append({"name": self.inputs.bgp_peer_groups.wan_overlay_peers.name, "activate": False}) # TODO: no elif elif self.shared_utils.overlay_evpn_vxlan is True: - peer_groups.append({"name": self._get_peer_group_name("evpn_overlay_peers"), "activate": False}) + peer_groups.append({"name": self.inputs.bgp_peer_groups.evpn_overlay_peers.name, "activate": False}) if self.shared_utils.overlay_routing_protocol == "ebgp" and ( - self.shared_utils.evpn_gateway_vxlan_l2 is True or self.shared_utils.evpn_gateway_vxlan_l3 is True + self.shared_utils.node_config.evpn_gateway.evpn_l2.enabled or self.shared_utils.node_config.evpn_gateway.evpn_l3.enabled ): - peer_groups.append({"name": self._get_peer_group_name("evpn_overlay_core"), "activate": False}) + peer_groups.append({"name": self.inputs.bgp_peer_groups.evpn_overlay_core.name, "activate": False}) if self.shared_utils.overlay_routing_protocol == "ibgp": if self.shared_utils.overlay_mpls is True: - peer_groups.append({"name": self._get_peer_group_name("mpls_overlay_peers"), "activate": False}) + peer_groups.append({"name": self.inputs.bgp_peer_groups.mpls_overlay_peers.name, "activate": False}) if self._is_mpls_server is True: - peer_groups.append({"name": self._get_peer_group_name("rr_overlay_peers"), "activate": False}) + peer_groups.append({"name": self.inputs.bgp_peer_groups.rr_overlay_peers.name, "activate": False}) if self._is_wan_server_with_peers: - peer_groups.append({"name": self._get_peer_group_name("wan_rr_overlay_peers"), "activate": False}) + peer_groups.append({"name": self.inputs.bgp_peer_groups.wan_rr_overlay_peers.name, "activate": False}) if self.shared_utils.overlay_ipvpn_gateway is True: - peer_groups.append({"name": self._get_peer_group_name("ipvpn_gateway_peers"), "activate": False}) + peer_groups.append({"name": self.inputs.bgp_peer_groups.ipvpn_gateway_peers.name, "activate": False}) return {"peer_groups": peer_groups} - def _get_peer_group_name(self: AvdStructuredConfigOverlay, key: str) -> str: - """Helper to retrieve the configured peer_group name for the given key.""" - return self.shared_utils.bgp_peer_groups[key]["name"] - def _address_family_evpn(self: AvdStructuredConfigOverlay) -> dict | None: address_family_evpn = {} @@ -221,41 +220,41 @@ def _address_family_evpn(self: AvdStructuredConfigOverlay) -> dict | None: if self.shared_utils.overlay_evpn_vxlan is True: if self.shared_utils.is_wan_router: overlay_peer_group = { - "name": self._get_peer_group_name("wan_overlay_peers"), + "name": self.inputs.bgp_peer_groups.wan_overlay_peers.name, "activate": True, - "encapsulation": self.shared_utils.wan_encapsulation, + "encapsulation": self.inputs.wan_encapsulation, } else: - overlay_peer_group = {"name": self._get_peer_group_name("evpn_overlay_peers"), "activate": True} + overlay_peer_group = {"name": self.inputs.bgp_peer_groups.evpn_overlay_peers.name, "activate": True} if self.shared_utils.overlay_routing_protocol == "ebgp": - if self.shared_utils.evpn_gateway_vxlan_l2 is True or self.shared_utils.evpn_gateway_vxlan_l3 is True: + if self.shared_utils.node_config.evpn_gateway.evpn_l2.enabled or self.shared_utils.node_config.evpn_gateway.evpn_l3.enabled: peer_groups.append( { - "name": self._get_peer_group_name("evpn_overlay_core"), + "name": self.inputs.bgp_peer_groups.evpn_overlay_core.name, "domain_remote": True, "activate": True, }, ) - if self.shared_utils.evpn_gateway_vxlan_l3 is True: + if self.shared_utils.node_config.evpn_gateway.evpn_l3.enabled: address_family_evpn["neighbor_default"] = { "next_hop_self_received_evpn_routes": { "enable": True, - "inter_domain": self.shared_utils.evpn_gateway_vxlan_l3_inter_domain, + "inter_domain": self.shared_utils.node_config.evpn_gateway.evpn_l3.inter_domain, }, } if self.shared_utils.overlay_routing_protocol == "ibgp": # TODO: - assess this condition - both can't be true at the same time. if self.shared_utils.overlay_evpn_mpls is True and self.shared_utils.overlay_evpn_vxlan is not True: - overlay_peer_group = {"name": self._get_peer_group_name("mpls_overlay_peers"), "activate": True} + overlay_peer_group = {"name": self.inputs.bgp_peer_groups.mpls_overlay_peers.name, "activate": True} address_family_evpn["neighbor_default"] = {"encapsulation": "mpls"} if self.shared_utils.overlay_ler is True: address_family_evpn["neighbor_default"]["next_hop_self_source_interface"] = "Loopback0" if self._is_mpls_server is True: - peer_groups.append({"name": self._get_peer_group_name("rr_overlay_peers"), "activate": True}) + peer_groups.append({"name": self.inputs.bgp_peer_groups.rr_overlay_peers.name, "activate": True}) if self.shared_utils.overlay_vtep is True and self.shared_utils.evpn_role != "server" and overlay_peer_group: overlay_peer_group.update( @@ -268,9 +267,9 @@ def _address_family_evpn(self: AvdStructuredConfigOverlay) -> dict | None: if self._is_wan_server_with_peers: peer_groups.append( { - "name": self._get_peer_group_name("wan_rr_overlay_peers"), + "name": self.inputs.bgp_peer_groups.wan_rr_overlay_peers.name, "activate": True, - "encapsulation": self.shared_utils.wan_encapsulation, + "encapsulation": self.inputs.wan_encapsulation, } ) @@ -282,20 +281,20 @@ def _address_family_evpn(self: AvdStructuredConfigOverlay) -> dict | None: # host flap detection & route pruning if self.shared_utils.overlay_vtep is True: - if (evpn_host_flap := get(self._hostvars, "evpn_hostflap_detection")) is not None: + if self.inputs.evpn_hostflap_detection: address_family_evpn["evpn_hostflap_detection"] = { - "window": evpn_host_flap.get("window", 180), - "threshold": evpn_host_flap.get("threshold", 5), - "enabled": evpn_host_flap.get("enabled", True), - "expiry_timeout": evpn_host_flap.get("expiry_timeout"), + "window": self.inputs.evpn_hostflap_detection.window, + "threshold": self.inputs.evpn_hostflap_detection.threshold, + "enabled": self.inputs.evpn_hostflap_detection.enabled, + "expiry_timeout": self.inputs.evpn_hostflap_detection.expiry_timeout, } - if get(self._hostvars, "evpn_import_pruning") is True: + if self.inputs.evpn_import_pruning: address_family_evpn["route"] = { "import_match_failure_action": "discard", } if self.shared_utils.overlay_dpath is True: - address_family_evpn["domain_identifier"] = get(self.shared_utils.switch_data_combined, "ipvpn_gateway.evpn_domain_id", default="65535:1") + address_family_evpn["domain_identifier"] = self.shared_utils.node_config.ipvpn_gateway.evpn_domain_id if self.shared_utils.is_wan_server: address_family_evpn["next_hop"] = {"resolution_disabled": True} @@ -311,7 +310,7 @@ def _address_family_evpn(self: AvdStructuredConfigOverlay) -> dict | None: { "ip_address": self._wan_ha_peer_vtep_ip(), "activate": True, - "encapsulation": self.shared_utils.wan_encapsulation, + "encapsulation": self.inputs.wan_encapsulation, } ] @@ -325,14 +324,14 @@ def _address_family_ipv4_sr_te(self: AvdStructuredConfigOverlay) -> dict | None: address_family_ipv4_sr_te = { "peer_groups": [ { - "name": self._get_peer_group_name("wan_overlay_peers"), + "name": self.inputs.bgp_peer_groups.wan_overlay_peers.name, "activate": True, }, ], } if self._is_wan_server_with_peers: - address_family_ipv4_sr_te["peer_groups"].append({"name": self._get_peer_group_name("wan_rr_overlay_peers"), "activate": True}) + address_family_ipv4_sr_te["peer_groups"].append({"name": self.inputs.bgp_peer_groups.wan_rr_overlay_peers.name, "activate": True}) return address_family_ipv4_sr_te @@ -344,7 +343,7 @@ def _address_family_link_state(self: AvdStructuredConfigOverlay) -> dict | None: address_family_link_state = { "peer_groups": [ { - "name": self._get_peer_group_name("wan_overlay_peers"), + "name": self.inputs.bgp_peer_groups.wan_overlay_peers.name, "activate": True, }, ], @@ -363,7 +362,7 @@ def _address_family_link_state(self: AvdStructuredConfigOverlay) -> dict | None: address_family_link_state["path_selection"] = {"roles": {"producer": True}} if self._is_wan_server_with_peers: - address_family_link_state["peer_groups"].append({"name": self._get_peer_group_name("wan_rr_overlay_peers"), "activate": True}) + address_family_link_state["peer_groups"].append({"name": self.inputs.bgp_peer_groups.wan_rr_overlay_peers.name, "activate": True}) return address_family_link_state @@ -374,7 +373,7 @@ def _address_family_path_selection(self: AvdStructuredConfigOverlay) -> dict | N address_family_path_selection = { "peer_groups": [ { - "name": self._get_peer_group_name("wan_overlay_peers"), + "name": self.inputs.bgp_peer_groups.wan_overlay_peers.name, "activate": True, }, ], @@ -382,7 +381,7 @@ def _address_family_path_selection(self: AvdStructuredConfigOverlay) -> dict | N } if self._is_wan_server_with_peers: - address_family_path_selection["peer_groups"].append({"name": self._get_peer_group_name("wan_rr_overlay_peers"), "activate": True}) + address_family_path_selection["peer_groups"].append({"name": self.inputs.bgp_peer_groups.wan_rr_overlay_peers.name, "activate": True}) return address_family_path_selection @@ -392,19 +391,19 @@ def _address_family_rtc(self: AvdStructuredConfigOverlay) -> dict | None: if the evpn_role is server, enable default_route_target only """ - if self.shared_utils.evpn_overlay_bgp_rtc is not True: + if not self.inputs.evpn_overlay_bgp_rtc: return None address_family_rtc = {} peer_groups = [] - evpn_overlay_peers = {"name": self._get_peer_group_name("evpn_overlay_peers")} + evpn_overlay_peers = {"name": self.inputs.bgp_peer_groups.evpn_overlay_peers.name} if self.shared_utils.overlay_evpn_vxlan is True: evpn_overlay_peers["activate"] = True if self.shared_utils.overlay_routing_protocol == "ebgp": - if self.shared_utils.evpn_gateway_vxlan_l2 is True or self.shared_utils.evpn_gateway_vxlan_l3 is True: - core_peer_group = {"name": self._get_peer_group_name("evpn_overlay_core"), "activate": True} + if self.shared_utils.node_config.evpn_gateway.evpn_l2.enabled or self.shared_utils.node_config.evpn_gateway.evpn_l3.enabled: + core_peer_group = {"name": self.inputs.bgp_peer_groups.evpn_overlay_core.name, "activate": True} # TODO: (@Claus) told me to remove this if self.shared_utils.evpn_role == "server": core_peer_group["default_route_target"] = {"only": True} @@ -417,7 +416,7 @@ def _address_family_rtc(self: AvdStructuredConfigOverlay) -> dict | None: if self.shared_utils.overlay_routing_protocol == "ibgp": if self.shared_utils.overlay_mpls is True: - mpls_peer_group = {"name": self._get_peer_group_name("mpls_overlay_peers"), "activate": True} + mpls_peer_group = {"name": self.inputs.bgp_peer_groups.mpls_overlay_peers.name, "activate": True} if self.shared_utils.evpn_role == "server" or self.shared_utils.mpls_overlay_role == "server": mpls_peer_group["default_route_target"] = {"only": True} peer_groups.append(mpls_peer_group) @@ -446,20 +445,20 @@ def _address_family_vpn_ipvx(self: AvdStructuredConfigOverlay, version: int) -> peer_groups = [] if self.shared_utils.overlay_ipvpn_gateway is True: - peer_groups.append({"name": self._get_peer_group_name("ipvpn_gateway_peers"), "activate": True}) + peer_groups.append({"name": self.inputs.bgp_peer_groups.ipvpn_gateway_peers.name, "activate": True}) if self.shared_utils.overlay_routing_protocol == "ibgp": if self.shared_utils.overlay_mpls is True: - peer_groups.append({"name": self._get_peer_group_name("mpls_overlay_peers"), "activate": True}) + peer_groups.append({"name": self.inputs.bgp_peer_groups.mpls_overlay_peers.name, "activate": True}) if self.shared_utils.mpls_overlay_role == "server": - peer_groups.append({"name": self._get_peer_group_name("rr_overlay_peers"), "activate": True}) + peer_groups.append({"name": self.inputs.bgp_peer_groups.rr_overlay_peers.name, "activate": True}) if peer_groups: address_family_vpn_ipvx["peer_groups"] = peer_groups if self.shared_utils.overlay_dpath is True: - address_family_vpn_ipvx["domain_identifier"] = get(self.shared_utils.switch_data_combined, "ipvpn_gateway.ipvpn_domain_id", default="65535:2") + address_family_vpn_ipvx["domain_identifier"] = self.shared_utils.node_config.ipvpn_gateway.ipvpn_domain_id return address_family_vpn_ipvx @@ -476,7 +475,7 @@ def _create_neighbor( "peer_group": peer_group, "peer": name, "description": AvdStringFormatter().format( - self.shared_utils.overlay_bgp_peer_description, **strip_empties_from_dict({"peer": name, "peer_interface": overlay_peering_interface}) + self.inputs.overlay_bgp_peer_description, **strip_empties_from_dict({"peer": name, "peer_interface": overlay_peering_interface}) ), } @@ -486,7 +485,7 @@ def _create_neighbor( raise AristaAvdError(msg) neighbor["remote_as"] = remote_as - if self.shared_utils.shutdown_bgp_towards_undeployed_peers is True and name in self._avd_overlay_peers: + if self.inputs.shutdown_bgp_towards_undeployed_peers and name in self._avd_overlay_peers: peer_facts = self.shared_utils.get_peer_facts(name) if peer_facts["is_deployed"] is False: neighbor["shutdown"] = True @@ -501,12 +500,12 @@ def _neighbors(self: AvdStructuredConfigOverlay) -> list | None: neighbor = self._create_neighbor( data["ip_address"], route_server, - self._get_peer_group_name("evpn_overlay_peers"), + self.inputs.bgp_peer_groups.evpn_overlay_peers.name, remote_as=data["bgp_as"], overlay_peering_interface=data.get("overlay_peering_interface"), ) - if self.shared_utils.evpn_prevent_readvertise_to_server is True: + if self.inputs.evpn_prevent_readvertise_to_server: neighbor["route_map_out"] = f"RM-EVPN-FILTER-AS{data['bgp_as']}" neighbors.append(neighbor) @@ -514,7 +513,7 @@ def _neighbors(self: AvdStructuredConfigOverlay) -> list | None: neighbor = self._create_neighbor( data["ip_address"], route_client, - self._get_peer_group_name("evpn_overlay_peers"), + self.inputs.bgp_peer_groups.evpn_overlay_peers.name, remote_as=data["bgp_as"], overlay_peering_interface=data.get("overlay_peering_interface"), ) @@ -524,7 +523,7 @@ def _neighbors(self: AvdStructuredConfigOverlay) -> list | None: neighbor = self._create_neighbor( data["ip_address"], gw_remote_peer, - self._get_peer_group_name("evpn_overlay_core"), + self.inputs.bgp_peer_groups.evpn_overlay_core.name, remote_as=data["bgp_as"], overlay_peering_interface=data.get("overlay_peering_interface"), ) @@ -536,7 +535,7 @@ def _neighbors(self: AvdStructuredConfigOverlay) -> list | None: neighbor = self._create_neighbor( data["ip_address"], route_reflector, - self._get_peer_group_name("mpls_overlay_peers"), + self.inputs.bgp_peer_groups.mpls_overlay_peers.name, overlay_peering_interface=data.get("overlay_peering_interface"), ) neighbors.append(neighbor) @@ -545,7 +544,7 @@ def _neighbors(self: AvdStructuredConfigOverlay) -> list | None: neighbor = self._create_neighbor( data["ip_address"], route_client, - self._get_peer_group_name("mpls_overlay_peers"), + self.inputs.bgp_peer_groups.mpls_overlay_peers.name, overlay_peering_interface=data.get("overlay_peering_interface"), ) neighbors.append(neighbor) @@ -554,7 +553,7 @@ def _neighbors(self: AvdStructuredConfigOverlay) -> list | None: neighbor = self._create_neighbor( data["ip_address"], mesh_pe, - self._get_peer_group_name("mpls_overlay_peers"), + self.inputs.bgp_peer_groups.mpls_overlay_peers.name, overlay_peering_interface=data.get("overlay_peering_interface"), ) neighbors.append(neighbor) @@ -564,7 +563,7 @@ def _neighbors(self: AvdStructuredConfigOverlay) -> list | None: neighbor = self._create_neighbor( data["ip_address"], rr_peer, - self._get_peer_group_name("rr_overlay_peers"), + self.inputs.bgp_peer_groups.rr_overlay_peers.name, overlay_peering_interface=data.get("overlay_peering_interface"), ) neighbors.append(neighbor) @@ -574,7 +573,7 @@ def _neighbors(self: AvdStructuredConfigOverlay) -> list | None: neighbor = self._create_neighbor( data["ip_address"], route_server, - self._get_peer_group_name("evpn_overlay_peers"), + self.inputs.bgp_peer_groups.evpn_overlay_peers.name, overlay_peering_interface=data.get("overlay_peering_interface"), ) neighbors.append(neighbor) @@ -583,7 +582,7 @@ def _neighbors(self: AvdStructuredConfigOverlay) -> list | None: neighbor = self._create_neighbor( data["ip_address"], route_client, - self._get_peer_group_name("evpn_overlay_peers"), + self.inputs.bgp_peer_groups.evpn_overlay_peers.name, overlay_peering_interface=data.get("overlay_peering_interface"), ) neighbors.append(neighbor) @@ -592,11 +591,11 @@ def _neighbors(self: AvdStructuredConfigOverlay) -> list | None: if not self._ip_in_listen_ranges(self.shared_utils.vtep_ip, self.shared_utils.wan_listen_ranges): msg = f"{self.shared_utils.vtep_loopback} IP {self.shared_utils.vtep_ip} is not in the Route Reflector listen range prefixes" raise AristaAvdError(msg) - for wan_route_server, data in self.shared_utils.filtered_wan_route_servers.items(): + for wan_route_server in self.shared_utils.filtered_wan_route_servers: neighbor = self._create_neighbor( - data["vtep_ip"], - wan_route_server, - self._get_peer_group_name("wan_overlay_peers"), + wan_route_server.vtep_ip, + wan_route_server.hostname, + self.inputs.bgp_peer_groups.wan_overlay_peers.name, overlay_peering_interface=self.shared_utils.vtep_loopback, ) neighbors.append(neighbor) @@ -617,11 +616,11 @@ def _neighbors(self: AvdStructuredConfigOverlay) -> list | None: if self.shared_utils.is_wan_server: # No neighbor configured on the `wan_overlay_peers` peer group as it is covered by listen ranges - for wan_route_server, data in self.shared_utils.filtered_wan_route_servers.items(): + for wan_route_server in self.shared_utils.filtered_wan_route_servers: neighbor = self._create_neighbor( - data["vtep_ip"], - wan_route_server, - self._get_peer_group_name("wan_rr_overlay_peers"), + wan_route_server.vtep_ip, + wan_route_server.hostname, + self.inputs.bgp_peer_groups.wan_rr_overlay_peers.name, overlay_peering_interface=self.shared_utils.vtep_loopback, ) neighbors.append(neighbor) @@ -630,13 +629,13 @@ def _neighbors(self: AvdStructuredConfigOverlay) -> list | None: neighbor = self._create_neighbor( data["ip_address"], ipvpn_gw_peer, - self._get_peer_group_name("ipvpn_gateway_peers"), + self.inputs.bgp_peer_groups.ipvpn_gateway_peers.name, remote_as=data["bgp_as"], overlay_peering_interface=data.get("overlay_peering_interface"), ) # Add ebgp_multihop if the gw peer is an ebgp peer. - if data["bgp_as"] != default(self._ipvpn_gateway_local_as, self.shared_utils.bgp_as): - neighbor["ebgp_multihop"] = self.shared_utils.evpn_ebgp_gateway_multihop + if data["bgp_as"] != default(self.shared_utils.node_config.ipvpn_gateway.local_as, self.shared_utils.bgp_as): + neighbor["ebgp_multihop"] = self.inputs.evpn_ebgp_gateway_multihop neighbors.append(neighbor) @@ -645,10 +644,12 @@ def _neighbors(self: AvdStructuredConfigOverlay) -> list | None: return None - def _ip_in_listen_ranges(self: AvdStructuredConfigOverlay, source_ip: str, listen_range_prefixes: list) -> bool: + def _ip_in_listen_ranges( + self: AvdStructuredConfigOverlay, source_ip: str, listen_range_prefixes: EosDesigns.BgpPeerGroups.WanOverlayPeers.ListenRangePrefixes + ) -> bool: """Check if our source IP is in any of the listen range prefixes.""" - source_ip = ipaddress.ip_address(source_ip) - return any(source_ip in ipaddress.ip_network(prefix) for prefix in listen_range_prefixes) + ip = ipaddress.ip_address(source_ip) + return any(ip in ipaddress.ip_network(prefix) for prefix in listen_range_prefixes) def _bgp_overlay_dpath(self: AvdStructuredConfigOverlay) -> dict | None: if self.shared_utils.overlay_dpath is True: diff --git a/python-avd/pyavd/_eos_designs/structured_config/overlay/router_path_selection.py b/python-avd/pyavd/_eos_designs/structured_config/overlay/router_path_selection.py index acfd3497703..6fa41159a2b 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/overlay/router_path_selection.py +++ b/python-avd/pyavd/_eos_designs/structured_config/overlay/router_path_selection.py @@ -7,7 +7,7 @@ from typing import TYPE_CHECKING from pyavd._errors import AristaAvdError -from pyavd._utils import get, get_ip_from_ip_prefix, get_item, strip_empties_from_dict +from pyavd._utils import get, get_ip_from_ip_prefix, strip_empties_from_dict from .utils import UtilsMixin @@ -29,7 +29,7 @@ def router_path_selection(self: AvdStructuredConfigOverlay) -> dict | None: return None router_path_selection = { - "tcp_mss_ceiling": {"ipv4_segment_size": get(self.shared_utils.switch_data_combined, "dps_mss_ipv4", default="auto")}, + "tcp_mss_ceiling": {"ipv4_segment_size": self.shared_utils.node_config.dps_mss_ipv4}, "path_groups": self._get_path_groups(), } @@ -38,39 +38,31 @@ def router_path_selection(self: AvdStructuredConfigOverlay) -> dict | None: return strip_empties_from_dict(router_path_selection) - @cached_property - def _cp_ipsec_profile_name(self: AvdStructuredConfigOverlay) -> str: - """Returns the IPsec profile name to use for Control-Plane.""" - return get(self._hostvars, "wan_ipsec_profiles.control_plane.profile_name", default="CP-PROFILE") - @cached_property def _dp_ipsec_profile_name(self: AvdStructuredConfigOverlay) -> str: """Returns the IPsec profile name to use for Data-Plane. - If no data-plane config is present for IPsec, default to _cp_ipsec_profile_name + If no data-plane config is present for IPsec, default to the control-plane profile-name. """ - if (data_plane := get(self._hostvars, "wan_ipsec_profiles.data_plane")) is not None: - return get(data_plane, "profile_name", default="DP-PROFILE") - return self._cp_ipsec_profile_name + if self.inputs.wan_ipsec_profiles.data_plane: + return self.inputs.wan_ipsec_profiles.data_plane.profile_name + return self.inputs.wan_ipsec_profiles.control_plane.profile_name def _get_path_groups(self: AvdStructuredConfigOverlay) -> list: """Generate the required path-groups locally.""" path_groups = [] # Configure all path-groups on Pathfinders and AutoVPN RRs. Otherwise only configure the local path-groups - path_groups_to_configure = self.shared_utils.wan_path_groups if self.shared_utils.is_wan_server else self.shared_utils.wan_local_path_groups - - local_path_groups_names = [path_group["name"] for path_group in self.shared_utils.wan_local_path_groups] + path_groups_to_configure = self.inputs.wan_path_groups if self.shared_utils.is_wan_server else self.shared_utils.wan_local_path_groups for path_group in path_groups_to_configure: - pg_name = path_group.get("name") - ipsec = path_group.get("ipsec", {}) - is_local_pg = pg_name in local_path_groups_names - disable_dynamic_peer_ipsec = is_local_pg and not ipsec.get("dynamic_peers", True) + pg_name = path_group.name + is_local_pg = pg_name in self.shared_utils.wan_local_path_group_names + disable_dynamic_peer_ipsec = is_local_pg and not path_group.ipsec.dynamic_peers path_group_data = { "name": pg_name, - "id": self._get_path_group_id(pg_name, path_group.get("id")), + "id": self._get_path_group_id(pg_name, path_group.id), "local_interfaces": self._get_local_interfaces_for_path_group(pg_name), "dynamic_peers": self._get_dynamic_peers(disable_dynamic_peer_ipsec), "static_peers": self._get_static_peers_for_path_group(pg_name), @@ -78,12 +70,11 @@ def _get_path_groups(self: AvdStructuredConfigOverlay) -> list: if is_local_pg: # On pathfinder IPsec profile is not required for non local path_groups - if ipsec.get("static_peers", True): - path_group_data["ipsec_profile"] = self._cp_ipsec_profile_name + if path_group.ipsec.static_peers: + path_group_data["ipsec_profile"] = self.inputs.wan_ipsec_profiles.control_plane.profile_name # KeepAlive config is not required for non local path_groups - keepalive = path_group.get("dps_keepalive", {}) - if (interval := keepalive.get("interval")) is not None: + if interval := path_group.dps_keepalive.interval: if interval == "auto": path_group_data["keepalive"] = {"auto": True} else: @@ -95,7 +86,7 @@ def _get_path_groups(self: AvdStructuredConfigOverlay) -> list: raise AristaAvdError(msg) path_group_data["keepalive"] = { "interval": int(interval), - "failure_threshold": get(keepalive, "failure_threshold", default=5), + "failure_threshold": path_group.dps_keepalive.failure_threshold, } path_groups.append(path_group_data) @@ -108,8 +99,8 @@ def _get_path_groups(self: AvdStructuredConfigOverlay) -> list: def _generate_ha_path_group(self: AvdStructuredConfigOverlay) -> dict: """Called only when self.shared_utils.wan_ha is True or on Pathfinders.""" ha_path_group = { - "name": self.shared_utils.wan_ha_path_group_name, - "id": self._get_path_group_id(self.shared_utils.wan_ha_path_group_name), + "name": self.inputs.wan_ha.lan_ha_path_group_name, + "id": self._get_path_group_id(self.inputs.wan_ha.lan_ha_path_group_name), "flow_assignment": "lan", } if self.shared_utils.is_cv_pathfinder_server: @@ -154,21 +145,23 @@ def _get_path_group_id(self: AvdStructuredConfigOverlay, path_group_name: str, c TODO: - implement algorithm to auto assign IDs - cf internal documentation TODO: - also implement algorithm for cross connects on public path_groups. """ - if path_group_name == self.shared_utils.wan_ha_path_group_name: + if path_group_name == self.inputs.wan_ha.lan_ha_path_group_name: return 65535 if config_id is not None: return config_id return 500 - def _get_local_interfaces_for_path_group(self: AvdStructuredConfigOverlay, path_group_name: str) -> list | None: + def _get_local_interfaces_for_path_group(self: AvdStructuredConfigOverlay, path_group_name: str) -> list: """ Generate the router_path_selection.local_interfaces list. For AUTOVPN clients, configure the stun server profiles as appropriate """ local_interfaces = [] - path_group = get_item(self.shared_utils.wan_local_path_groups, "name", path_group_name, default={}) - for interface in path_group.get("interfaces", []): + if path_group_name not in self.shared_utils.wan_local_path_groups: + return local_interfaces + + for interface in self.shared_utils.wan_local_path_groups[path_group_name]._interfaces: local_interface = {"name": get(interface, "name", required=True)} if self.shared_utils.is_wan_client and self.shared_utils.should_connect_to_wan_rs([path_group_name]): @@ -196,20 +189,20 @@ def _get_static_peers_for_path_group(self: AvdStructuredConfigOverlay, path_grou return None static_peers = [] - for wan_route_server_name, wan_route_server in self.shared_utils.filtered_wan_route_servers.items(): - if (path_group := get_item(get(wan_route_server, "wan_path_groups", default=[]), "name", path_group_name)) is not None: - ipv4_addresses = [ - get_ip_from_ip_prefix(public_ip) - for interface_dict in get(path_group, "interfaces", required=True) - if (public_ip := interface_dict.get("public_ip")) is not None - ] - - static_peers.append( - { - "router_ip": get(wan_route_server, "vtep_ip", required=True), - "name": wan_route_server_name, - "ipv4_addresses": ipv4_addresses, - }, - ) + for wan_route_server in self.shared_utils.filtered_wan_route_servers: + if path_group_name not in wan_route_server.path_groups: + continue + + ipv4_addresses = [ + get_ip_from_ip_prefix(interface.public_ip) for interface in wan_route_server.path_groups[path_group_name].interfaces if interface.public_ip + ] + + static_peers.append( + { + "router_ip": wan_route_server.vtep_ip, + "name": wan_route_server.hostname, + "ipv4_addresses": ipv4_addresses, + }, + ) return static_peers diff --git a/python-avd/pyavd/_eos_designs/structured_config/overlay/stun.py b/python-avd/pyavd/_eos_designs/structured_config/overlay/stun.py index b05c950db23..c393563ba2f 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/overlay/stun.py +++ b/python-avd/pyavd/_eos_designs/structured_config/overlay/stun.py @@ -30,7 +30,7 @@ def stun(self: AvdStructuredConfigOverlay) -> dict | None: stun = {} if self.shared_utils.is_wan_server: - local_interfaces = [wan_interface["name"] for wan_interface in self.shared_utils.wan_interfaces] + local_interfaces = [wan_interface.name for wan_interface in self.shared_utils.wan_interfaces] stun["server"] = { "local_interfaces": local_interfaces, "ssl_profile": self.shared_utils.wan_stun_dtls_profile_name, diff --git a/python-avd/pyavd/_eos_designs/structured_config/overlay/utils.py b/python-avd/pyavd/_eos_designs/structured_config/overlay/utils.py index e8f3e01678c..9745d3e7f0b 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/overlay/utils.py +++ b/python-avd/pyavd/_eos_designs/structured_config/overlay/utils.py @@ -38,32 +38,30 @@ def _evpn_gateway_remote_peers(self: AvdStructuredConfigOverlay) -> dict: evpn_gateway_remote_peers = {} - evpn_gateway_remote_peers_list = get(self.shared_utils.switch_data_combined, "evpn_gateway.remote_peers", default=[]) + for remote_peer in self.shared_utils.node_config.evpn_gateway.remote_peers._natural_sorted(): + remote_peer_name = remote_peer.hostname - for gw_remote_peer_dict in natural_sort(evpn_gateway_remote_peers_list, sort_key="hostname"): # These remote gateways can be outside of the inventory or in the inventory - gw_remote_peer = gw_remote_peer_dict["hostname"] - gw_info = strip_empties_from_dict( { - "bgp_as": str(_as) if (_as := gw_remote_peer_dict.get("bgp_as")) else None, - "ip_address": gw_remote_peer_dict.get("ip_address"), + "bgp_as": remote_peer.bgp_as, + "ip_address": remote_peer.ip_address, # Not adding the "overlay_peering_interface" since we do not know it for this device. Only used for description. } ) - peer_facts = self.shared_utils.get_peer_facts(gw_remote_peer, required=False) + peer_facts = self.shared_utils.get_peer_facts(remote_peer_name, required=False) if peer_facts is None: # No matching host found in the inventory for this remote gateway - evpn_gateway_remote_peers[gw_remote_peer] = gw_info + evpn_gateway_remote_peers[remote_peer_name] = gw_info else: # Found a matching name for this remote gateway in the inventory - self._append_peer(evpn_gateway_remote_peers, gw_remote_peer, peer_facts) + self._append_peer(evpn_gateway_remote_peers, remote_peer_name, peer_facts) # Apply potential override if present in the input variables - evpn_gateway_remote_peers[gw_remote_peer].update(strip_empties_from_dict(gw_info)) + evpn_gateway_remote_peers[remote_peer_name].update(strip_empties_from_dict(gw_info)) - if any(key not in evpn_gateway_remote_peers[gw_remote_peer] for key in ["bgp_as", "ip_address"]): - msg = f"The EVPN Gateway remote peer '{gw_remote_peer}' is missing either a `bpg_as` or an `ip_address`." + if any(key not in evpn_gateway_remote_peers[remote_peer_name] for key in ["bgp_as", "ip_address"]): + msg = f"The EVPN Gateway remote peer '{remote_peer_name}' is missing either a `bpg_as` or an `ip_address`." raise AristaAvdError(msg) return evpn_gateway_remote_peers @@ -120,10 +118,6 @@ def _is_peer_mpls_client(self: AvdStructuredConfigOverlay, peer_facts: dict) -> def _is_peer_mpls_server(self: AvdStructuredConfigOverlay, peer_facts: dict) -> bool: return peer_facts.get("mpls_overlay_role") == "server" or (peer_facts.get("evpn_role") == "server" and get(peer_facts, "overlay.evpn_mpls") is True) - @cached_property - def _ipvpn_gateway_local_as(self: AvdStructuredConfigOverlay) -> str | None: - return str(_as) if (_as := get(self.shared_utils.switch_data_combined, "ipvpn_gateway.local_as")) is not None else None - @cached_property def _ipvpn_gateway_remote_peers(self: AvdStructuredConfigOverlay) -> dict: if self.shared_utils.overlay_ipvpn_gateway is not True: @@ -131,21 +125,14 @@ def _ipvpn_gateway_remote_peers(self: AvdStructuredConfigOverlay) -> dict: ipvpn_gateway_remote_peers = {} - for ipvpn_gw_peer_dict in natural_sort( - get( - self.shared_utils.switch_data_combined, - "ipvpn_gateway.remote_peers", - default=[], - ), - "hostname", - ): + for remote_peer in self.shared_utils.node_config.ipvpn_gateway.remote_peers._natural_sorted(): # These remote gw are outside of the inventory - bgp_as = ipvpn_gw_peer_dict["bgp_as"] + bgp_as = remote_peer.bgp_as - ipvpn_gateway_remote_peers[ipvpn_gw_peer_dict["hostname"]] = { + ipvpn_gateway_remote_peers[remote_peer.hostname] = { "bgp_as": str(bgp_as) if bgp_as is not None else None, - "ip_address": ipvpn_gw_peer_dict["ip_address"], + "ip_address": remote_peer.ip_address, # Not adding the "overlay_peering_interface" since we do not know it for this device. Only used for description. } @@ -170,14 +157,10 @@ def _mpls_route_clients(self: AvdStructuredConfigOverlay) -> dict: @cached_property def _mpls_mesh_pe(self: AvdStructuredConfigOverlay) -> dict: - if self.shared_utils.overlay_mpls is not True: - return {} - - if get(self._hostvars, "bgp_mesh_pes") is not True: + if not self.shared_utils.overlay_mpls or not self.inputs.bgp_mesh_pes: return {} mpls_mesh_pe = {} - for fabric_switch in self.shared_utils.all_fabric_devices: if self._mpls_route_reflectors is not None and fabric_switch in self._mpls_route_reflectors: continue @@ -284,18 +267,18 @@ def _stun_server_profile_name(self: AvdStructuredConfigOverlay, wan_route_server def _stun_server_profiles(self: AvdStructuredConfigOverlay) -> dict: """Return a dictionary of _stun_server_profiles with ip_address per local path_group.""" stun_server_profiles = {} - for wan_route_server, data in self.shared_utils.filtered_wan_route_servers.items(): - for path_group in data.get("wan_path_groups", []): - stun_server_profiles.setdefault(path_group["name"], []).extend( + for wan_route_server in self.shared_utils.filtered_wan_route_servers: + for path_group in wan_route_server.path_groups: + stun_server_profiles.setdefault(path_group.name, []).extend( { - "name": self._stun_server_profile_name(wan_route_server, path_group["name"], get(interface_dict, "name", required=True)), - "ip_address": get(interface_dict, "public_ip", required=True), + "name": self._stun_server_profile_name(wan_route_server.hostname, path_group.name, interface.name), + "ip_address": interface.public_ip, "ssl_profile": self.shared_utils.wan_stun_dtls_profile_name, } - for interface_dict in get(path_group, "interfaces", required=True) + for interface in path_group.interfaces ) return stun_server_profiles - def _wan_ha_peer_vtep_ip(self) -> str: + def _wan_ha_peer_vtep_ip(self: AvdStructuredConfigOverlay) -> str: peer_facts = self.shared_utils.get_peer_facts(self.shared_utils.wan_ha_peer, required=True) return get(peer_facts, "vtep_ip", required=True) diff --git a/python-avd/pyavd/_eos_designs/structured_config/underlay/ethernet_interfaces.py b/python-avd/pyavd/_eos_designs/structured_config/underlay/ethernet_interfaces.py index 3439b20833a..b082ff69790 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/underlay/ethernet_interfaces.py +++ b/python-avd/pyavd/_eos_designs/structured_config/underlay/ethernet_interfaces.py @@ -6,7 +6,7 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._errors import AristaAvdError +from pyavd._errors import AristaAvdError, AristaAvdMissingVariableError from pyavd._utils import append_if_not_duplicate, get, strip_null_from_data from pyavd.api.interface_descriptions import InterfaceDescriptionData from pyavd.j2filters import encrypt, natural_sort @@ -47,7 +47,7 @@ def ethernet_interfaces(self: AvdStructuredConfigUnderlay) -> list | None: "peer_type": link["peer_type"], "description": description, "speed": link.get("speed"), - "shutdown": self.shared_utils.shutdown_interfaces_towards_undeployed_peers and not link["peer_is_deployed"], + "shutdown": self.inputs.shutdown_interfaces_towards_undeployed_peers and not link["peer_is_deployed"], } # L3 interface @@ -56,7 +56,7 @@ def ethernet_interfaces(self: AvdStructuredConfigUnderlay) -> list | None: ethernet_interface.update( { "mtu": self.shared_utils.p2p_uplinks_mtu, - "service_profile": self.shared_utils.p2p_uplinks_qos_profile, + "service_profile": self.inputs.p2p_uplinks_qos_profile, "mac_security": link.get("mac_security"), "switchport": {"enabled": False}, "ipv6_enable": link.get("ipv6_enable"), @@ -72,11 +72,10 @@ def ethernet_interfaces(self: AvdStructuredConfigUnderlay) -> list | None: # Apply PTP profile config if using the new ptp config style if self.shared_utils.ptp_enabled: - ptp_config.update(self.shared_utils.ptp_profile) + ptp_config.update(self.shared_utils.ptp_profile._as_dict(include_default_values=True)) ptp_config["enable"] = True ptp_config.pop("profile", None) - ethernet_interface["ptp"] = ptp_config # MPLS @@ -99,28 +98,24 @@ def ethernet_interfaces(self: AvdStructuredConfigUnderlay) -> list | None: if self.shared_utils.underlay_ospf is True: ethernet_interface["ospf_network_point_to_point"] = True - ethernet_interface["ospf_area"] = self.shared_utils.underlay_ospf_area - ospf_authentication = get(self._hostvars, "underlay_ospf_authentication.enabled") - ospf_message_digest_keys = get(self._hostvars, "underlay_ospf_authentication.message_digest_keys") - if ospf_authentication is True and ospf_message_digest_keys is not None: - ospf_keys = [] - for ospf_key in ospf_message_digest_keys: - if not ("id" in ospf_key and "key" in ospf_key): - continue - - ospf_keys.append( - { - "id": ospf_key["id"], - "hash_algorithm": ospf_key.get("hash_algorithm", "sha512"), - "key": encrypt( - ospf_key["key"], - passwd_type="ospf_message_digest", # NOSONAR # noqa: S106 - key=ethernet_interface["name"], - hash_algorithm=ospf_key.get("hash_algorithm", "sha512"), - key_id=ospf_key["id"], - ), - }, - ) + ethernet_interface["ospf_area"] = self.inputs.underlay_ospf_area + ospf_authentication = self.inputs.underlay_ospf_authentication.enabled + ospf_message_digest_keys = self.inputs.underlay_ospf_authentication.message_digest_keys + if ospf_authentication and ospf_message_digest_keys: + ospf_keys = [ + { + "id": ospf_key.id, + "hash_algorithm": ospf_key.hash_algorithm, + "key": encrypt( + ospf_key.key, + passwd_type="ospf_message_digest", # NOSONAR # noqa: S106 + key=ethernet_interface["name"], + hash_algorithm=ospf_key.hash_algorithm, + key_id=ospf_key.id, + ), + } + for ospf_key in ospf_message_digest_keys + ] if len(ospf_keys) > 0: ethernet_interface["ospf_authentication"] = "message-digest" @@ -133,19 +128,19 @@ def ethernet_interfaces(self: AvdStructuredConfigUnderlay) -> list | None: ethernet_interface.update( { "isis_enable": self.shared_utils.isis_instance_name, - "isis_bfd": get(self._hostvars, "underlay_isis_bfd"), - "isis_metric": self.shared_utils.isis_default_metric, + "isis_bfd": self.inputs.underlay_isis_bfd or None, + "isis_metric": self.inputs.isis_default_metric, "isis_network_point_to_point": True, - "isis_circuit_type": self.shared_utils.isis_default_circuit_type, - } + "isis_circuit_type": self.inputs.isis_default_circuit_type, + }, ) - if (isis_authentication_mode := get(self._hostvars, "underlay_isis_authentication_mode")) is not None: - ethernet_interface.setdefault("isis_authentication", {}).setdefault("both", {})["mode"] = isis_authentication_mode + if self.inputs.underlay_isis_authentication_mode: + ethernet_interface.setdefault("isis_authentication", {}).setdefault("both", {})["mode"] = self.inputs.underlay_isis_authentication_mode - if (isis_authentication_key := get(self._hostvars, "underlay_isis_authentication_key")) is not None: + if self.inputs.underlay_isis_authentication_key is not None: ethernet_interface.setdefault("isis_authentication", {}).setdefault("both", {}).update( { - "key": isis_authentication_key, + "key": self.inputs.underlay_isis_authentication_key, "key_type": "7", } ) @@ -192,7 +187,7 @@ def ethernet_interfaces(self: AvdStructuredConfigUnderlay) -> list | None: "native_vlan": link.get("native_vlan"), }, }, - "service_profile": self.shared_utils.p2p_uplinks_qos_profile, + "service_profile": self.inputs.p2p_uplinks_qos_profile, "link_tracking_groups": link.get("link_tracking_groups"), "spanning_tree_portfast": link.get("spanning_tree_portfast"), "flow_tracker": link.get("flow_tracker"), @@ -232,7 +227,7 @@ def ethernet_interfaces(self: AvdStructuredConfigUnderlay) -> list | None: # TODO: - for now reusing the encapsulation as it is hardcoded to the VRF ID which is used as # subinterface name "description": description, - "shutdown": self.shared_utils.shutdown_interfaces_towards_undeployed_peers and not link["peer_is_deployed"], + "shutdown": self.inputs.shutdown_interfaces_towards_undeployed_peers and not link["peer_is_deployed"], "encapsulation_dot1q": {"vlan": subinterface["encapsulation_dot1q_vlan"]}, "ipv6_enable": subinterface.get("ipv6_enable"), "sflow": link.get("sflow"), @@ -265,10 +260,9 @@ def ethernet_interfaces(self: AvdStructuredConfigUnderlay) -> list | None: # Support l3_interface as sub interfaces subif_parent_interface_names = set() for l3_interface in self.shared_utils.l3_interfaces: - interface_name = l3_interface["name"] - if "." in interface_name: + if "." in l3_interface.name: # This is a subinterface so we need to ensure that the parent is created - parent_interface_name, _ = interface_name.split(".", maxsplit=1) + parent_interface_name, _ = l3_interface.name.split(".", maxsplit=1) subif_parent_interface_names.add(parent_interface_name) ethernet_interface = self._get_l3_interface_cfg(l3_interface) @@ -277,7 +271,7 @@ def ethernet_interfaces(self: AvdStructuredConfigUnderlay) -> list | None: list_of_dicts=ethernet_interfaces, primary_key="name", new_dict=ethernet_interface, - context=f"L3 Interfaces defined under {self.shared_utils.node_type_key_data['key']} l3_interfaces", + context=f"L3 Interfaces defined under {self.shared_utils.node_type_key_data.key} l3_interfaces", context_keys=["name", "peer", "peer_interface"], ) @@ -295,7 +289,7 @@ def ethernet_interfaces(self: AvdStructuredConfigUnderlay) -> list | None: list_of_dicts=ethernet_interfaces, primary_key="name", new_dict=parent_interface, - context=f"L3 Interfaces defined under {self.shared_utils.node_type_key_data['key']} l3_interfaces", + context=f"L3 Interfaces defined under {self.shared_utils.node_type_key_data.key} l3_interfaces", context_keys=["name", "peer", "peer_interface"], ) @@ -305,7 +299,7 @@ def ethernet_interfaces(self: AvdStructuredConfigUnderlay) -> list | None: list_of_dicts=ethernet_interfaces, primary_key="name", new_dict=wan_ha_interface, - context=f"L3 Interfaces defined under {self.shared_utils.node_type_key_data['key']} wan_ha.ha_interfaces", + context=f"L3 Interfaces defined under {self.shared_utils.node_type_key_data.key} wan_ha.ha_interfaces", context_keys=["name", "peer", "peer_interface"], ) @@ -325,9 +319,13 @@ def _get_direct_ha_ethernet_interfaces(self: AvdStructuredConfigUnderlay) -> lis direct_wan_ha_interfaces = [] - direct_wan_ha_links_flow_tracker = self.shared_utils.get_flow_tracker(get(self.shared_utils.switch_data_combined, "wan_ha"), "direct_wan_ha_links") + direct_wan_ha_links_flow_tracker = self.shared_utils.get_flow_tracker(self.shared_utils.node_config.wan_ha.flow_tracking) + + if not self.shared_utils.node_config.wan_ha.ha_interfaces: + msg = "wan_ha.ha_interfaces" + raise AristaAvdMissingVariableError(msg) - for index, interface in enumerate(get(self.shared_utils.switch_data_combined, "wan_ha.ha_interfaces", required=True)): + for index, interface in enumerate(self.shared_utils.node_config.wan_ha.ha_interfaces): description = self.shared_utils.interface_descriptions.wan_ha_ethernet_interface( InterfaceDescriptionData( shared_utils=self.shared_utils, @@ -350,8 +348,7 @@ def _get_direct_ha_ethernet_interfaces(self: AvdStructuredConfigUnderlay) -> lis "mode": "active", }, # TODO: do we need speed? - # TODO: do we need mtu - "mtu": self.shared_utils.configured_wan_ha_mtu, + "mtu": self.shared_utils.node_config.wan_ha.mtu, } ) else: @@ -366,7 +363,7 @@ def _get_direct_ha_ethernet_interfaces(self: AvdStructuredConfigUnderlay) -> lis "description": description, "ip_address": self.shared_utils.wan_ha_ip_addresses[index], "flow_tracker": direct_wan_ha_links_flow_tracker, - "mtu": self.shared_utils.configured_wan_ha_mtu, + "mtu": self.shared_utils.node_config.wan_ha.mtu, } ) diff --git a/python-avd/pyavd/_eos_designs/structured_config/underlay/loopback_interfaces.py b/python-avd/pyavd/_eos_designs/structured_config/underlay/loopback_interfaces.py index ba3da306207..0887b21c8e3 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/underlay/loopback_interfaces.py +++ b/python-avd/pyavd/_eos_designs/structured_config/underlay/loopback_interfaces.py @@ -7,7 +7,7 @@ from typing import TYPE_CHECKING from pyavd._errors import AristaAvdInvalidInputsError -from pyavd._utils import default, get +from pyavd._utils import default from pyavd.api.interface_descriptions import InterfaceDescriptionData from .utils import UtilsMixin @@ -37,9 +37,7 @@ def loopback_interfaces(self: AvdStructuredConfigUnderlay) -> list | None: InterfaceDescriptionData( shared_utils=self.shared_utils, interface="Loopback0", - description=default( - get(self._hostvars, "router_id_loopback_description"), get(self._hostvars, "overlay_loopback_description"), "ROUTER_ID" - ), + description=default(self.inputs.overlay_loopback_description, self.inputs.router_id_loopback_description), ), ), "shutdown": False, @@ -50,7 +48,7 @@ def loopback_interfaces(self: AvdStructuredConfigUnderlay) -> list | None: loopback0["ipv6_address"] = f"{self.shared_utils.ipv6_router_id}/128" if self.shared_utils.underlay_ospf: - loopback0["ospf_area"] = self.shared_utils.underlay_ospf_area + loopback0["ospf_area"] = self.inputs.underlay_ospf_area if self.shared_utils.underlay_ldp: loopback0["mpls"] = {"ldp": {"interface": True}} @@ -78,20 +76,18 @@ def loopback_interfaces(self: AvdStructuredConfigUnderlay) -> list | None: "name": self.shared_utils.vtep_loopback, "description": self.shared_utils.interface_descriptions.vtep_loopback_interface( InterfaceDescriptionData( - shared_utils=self.shared_utils, - interface=self.shared_utils.vtep_loopback, - description=get(self._hostvars, "vtep_loopback_description", default="VXLAN_TUNNEL_SOURCE"), + shared_utils=self.shared_utils, interface=self.shared_utils.vtep_loopback, description=self.inputs.vtep_loopback_description ) ), "shutdown": False, "ip_address": f"{self.shared_utils.vtep_ip}/32", } - if self.shared_utils.network_services_l3 is True and self.shared_utils.vtep_vvtep_ip is not None: - vtep_loopback["ip_address_secondaries"] = [self.shared_utils.vtep_vvtep_ip] + if self.shared_utils.network_services_l3 is True and self.inputs.vtep_vvtep_ip is not None: + vtep_loopback["ip_address_secondaries"] = [self.inputs.vtep_vvtep_ip] if self.shared_utils.underlay_ospf is True: - vtep_loopback["ospf_area"] = self.shared_utils.underlay_ospf_area + vtep_loopback["ospf_area"] = self.inputs.underlay_ospf_area if self.shared_utils.underlay_isis is True: vtep_loopback.update({"isis_enable": self.shared_utils.isis_instance_name, "isis_passive": True}) @@ -107,9 +103,9 @@ def loopback_interfaces(self: AvdStructuredConfigUnderlay) -> list | None: return loopback_interfaces @cached_property - def _node_sid(self: AvdStructuredConfigUnderlay) -> str: + def _node_sid(self: AvdStructuredConfigUnderlay) -> int: if self.shared_utils.id is None: msg = f"'id' is not set on '{self.shared_utils.hostname}' and is required to set node SID" raise AristaAvdInvalidInputsError(msg) - node_sid_base = int(get(self.shared_utils.switch_data_combined, "node_sid_base", 0)) - return self.shared_utils.id + node_sid_base + + return self.shared_utils.id + self.shared_utils.node_config.node_sid_base diff --git a/python-avd/pyavd/_eos_designs/structured_config/underlay/mpls.py b/python-avd/pyavd/_eos_designs/structured_config/underlay/mpls.py index 57c80c835c8..7b3806ab7d7 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/underlay/mpls.py +++ b/python-avd/pyavd/_eos_designs/structured_config/underlay/mpls.py @@ -33,7 +33,7 @@ def mpls(self: AvdStructuredConfigUnderlay) -> dict | None: "ip": True, "ldp": { "interface_disabled_default": True, - "router_id": self.shared_utils.router_id if not self.shared_utils.use_router_general_for_router_id else None, + "router_id": self.shared_utils.router_id if not self.inputs.use_router_general_for_router_id else None, "shutdown": False, "transport_address_interface": "Loopback0", }, diff --git a/python-avd/pyavd/_eos_designs/structured_config/underlay/port_channel_interfaces.py b/python-avd/pyavd/_eos_designs/structured_config/underlay/port_channel_interfaces.py index 04e631765c3..a9264779d2a 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/underlay/port_channel_interfaces.py +++ b/python-avd/pyavd/_eos_designs/structured_config/underlay/port_channel_interfaces.py @@ -60,7 +60,7 @@ def port_channel_interfaces(self: AvdStructuredConfigUnderlay) -> list | None: }, }, "shutdown": False, - "service_profile": self.shared_utils.p2p_uplinks_qos_profile, + "service_profile": self.inputs.p2p_uplinks_qos_profile, "link_tracking_groups": link.get("link_tracking_groups"), "sflow": link.get("sflow"), "flow_tracker": link.get("flow_tracker"), @@ -73,12 +73,12 @@ def port_channel_interfaces(self: AvdStructuredConfigUnderlay) -> list | None: port_channel_interface["switchport"]["trunk"]["allowed_vlan"] = vlans # Configure MLAG on MLAG switches if either 'mlag_on_orphan_port_channel_downlink' or 'link.mlag' is True - if self.shared_utils.mlag is True and any([get(self._hostvars, "mlag_on_orphan_port_channel_downlink", default=False), link.get("mlag", True)]): + if self.shared_utils.mlag is True and any([self.inputs.mlag_on_orphan_port_channel_downlink, link.get("mlag", True)]): port_channel_interface["mlag"] = int(link.get("channel_group_id")) if (short_esi := link.get("short_esi")) is not None: port_channel_interface["evpn_ethernet_segment"] = { - "identifier": f"{self.shared_utils.evpn_short_esi_prefix}{short_esi}", + "identifier": f"{self.inputs.evpn_short_esi_prefix}{short_esi}", "route_target": short_esi_to_route_target(short_esi), } port_channel_interface["lacp_id"] = short_esi.replace(":", ".") @@ -89,7 +89,7 @@ def port_channel_interfaces(self: AvdStructuredConfigUnderlay) -> list | None: # Apply PTP profile config if using the new ptp config style if self.shared_utils.ptp_enabled: - ptp_config.update(self.shared_utils.ptp_profile) + ptp_config.update(self.shared_utils.ptp_profile._as_dict(include_default_values=True)) ptp_config["enable"] = True ptp_config.pop("profile", None) @@ -129,8 +129,7 @@ def _get_direct_ha_port_channel_interface(self: AvdStructuredConfigUnderlay) -> if not self.shared_utils.use_port_channel_for_direct_ha: return None - direct_wan_ha_links_flow_tracker = self.shared_utils.get_flow_tracker(get(self.shared_utils.switch_data_combined, "wan_ha"), "direct_wan_ha_links") - + direct_wan_ha_links_flow_tracker = self.shared_utils.get_flow_tracker(self.shared_utils.node_config.wan_ha.flow_tracking) port_channel_name = f"Port-Channel{self.shared_utils.wan_ha_port_channel_id}" description = self.shared_utils.interface_descriptions.wan_ha_port_channel_interface( InterfaceDescriptionData( @@ -152,5 +151,5 @@ def _get_direct_ha_port_channel_interface(self: AvdStructuredConfigUnderlay) -> "description": description, "ip_address": self.shared_utils.wan_ha_ip_addresses[0], "flow_tracker": direct_wan_ha_links_flow_tracker, - "mtu": self.shared_utils.configured_wan_ha_mtu, + "mtu": self.shared_utils.node_config.wan_ha.mtu, } diff --git a/python-avd/pyavd/_eos_designs/structured_config/underlay/prefix_lists.py b/python-avd/pyavd/_eos_designs/structured_config/underlay/prefix_lists.py index bfe6defa9f8..3656132cc70 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/underlay/prefix_lists.py +++ b/python-avd/pyavd/_eos_designs/structured_config/underlay/prefix_lists.py @@ -32,7 +32,7 @@ def prefix_lists(self: AvdStructuredConfigUnderlay) -> list | None: if self.shared_utils.overlay_routing_protocol == "none": return None - if not self.shared_utils.underlay_filter_redistribute_connected: + if not self.inputs.underlay_filter_redistribute_connected: return None # IPv4 - PL-LOOPBACKS-EVPN-OVERLAY @@ -41,8 +41,8 @@ def prefix_lists(self: AvdStructuredConfigUnderlay) -> list | None: if self.shared_utils.overlay_vtep and self.shared_utils.vtep_loopback.lower() != "loopback0" and not self.shared_utils.is_wan_router: sequence_numbers.append({"sequence": 20, "action": f"permit {self.shared_utils.vtep_loopback_ipv4_pool} eq 32"}) - if self.shared_utils.vtep_vvtep_ip is not None and self.shared_utils.network_services_l3 is True and not self.shared_utils.is_wan_router: - sequence_numbers.append({"sequence": 30, "action": f"permit {self.shared_utils.vtep_vvtep_ip}"}) + if self.inputs.vtep_vvtep_ip is not None and self.shared_utils.network_services_l3 is True and not self.shared_utils.is_wan_router: + sequence_numbers.append({"sequence": 30, "action": f"permit {self.inputs.vtep_vvtep_ip}"}) prefix_lists = [{"name": "PL-LOOPBACKS-EVPN-OVERLAY", "sequence_numbers": sequence_numbers}] @@ -104,7 +104,7 @@ def ipv6_prefix_lists(self: AvdStructuredConfigUnderlay) -> list | None: if self.shared_utils.overlay_routing_protocol == "none" and not self.shared_utils.is_wan_router: return None - if not self.shared_utils.underlay_filter_redistribute_connected: + if not self.inputs.underlay_filter_redistribute_connected: return None # IPv6 - PL-LOOPBACKS-EVPN-OVERLAY-V6 diff --git a/python-avd/pyavd/_eos_designs/structured_config/underlay/route_maps.py b/python-avd/pyavd/_eos_designs/structured_config/underlay/route_maps.py index 7b3dc7b2e8c..c80922b4db3 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/underlay/route_maps.py +++ b/python-avd/pyavd/_eos_designs/structured_config/underlay/route_maps.py @@ -35,7 +35,7 @@ def route_maps(self: AvdStructuredConfigUnderlay) -> list | None: route_maps = [] - if self.shared_utils.overlay_routing_protocol != "none" and self.shared_utils.underlay_filter_redistribute_connected: + if self.shared_utils.overlay_routing_protocol != "none" and self.inputs.underlay_filter_redistribute_connected: # RM-CONN-2-BGP sequence_10 = { "sequence": 10, diff --git a/python-avd/pyavd/_eos_designs/structured_config/underlay/router_bgp.py b/python-avd/pyavd/_eos_designs/structured_config/underlay/router_bgp.py index a92098118dc..835147cb981 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/underlay/router_bgp.py +++ b/python-avd/pyavd/_eos_designs/structured_config/underlay/router_bgp.py @@ -30,13 +30,13 @@ def router_bgp(self: AvdStructuredConfigUnderlay) -> dict | None: router_bgp = {} peer_group = { - "name": self.shared_utils.bgp_peer_groups["ipv4_underlay_peers"]["name"], + "name": self.inputs.bgp_peer_groups.ipv4_underlay_peers.name, "type": "ipv4", - "password": self.shared_utils.bgp_peer_groups["ipv4_underlay_peers"]["password"], - "bfd": self.shared_utils.bgp_peer_groups["ipv4_underlay_peers"]["bfd"], + "password": self.inputs.bgp_peer_groups.ipv4_underlay_peers.password, + "bfd": self.inputs.bgp_peer_groups.ipv4_underlay_peers.bfd or None, "maximum_routes": 12000, "send_community": "all", - "struct_cfg": self.shared_utils.bgp_peer_groups["ipv4_underlay_peers"]["structured_config"], + "struct_cfg": self.inputs.bgp_peer_groups.ipv4_underlay_peers.structured_config._as_dict(strip_values=()) or None, } if self.shared_utils.overlay_routing_protocol == "ibgp" and self.shared_utils.is_cv_pathfinder_router: @@ -53,20 +53,20 @@ def router_bgp(self: AvdStructuredConfigUnderlay) -> dict | None: # TODO: - see if it makes sense to extract logic in method address_family_ipv4_peer_group = {"activate": True} - if self.shared_utils.underlay_rfc5549 is True: + if self.inputs.underlay_rfc5549 is True: address_family_ipv4_peer_group["next_hop"] = {"address_family_ipv6": {"enabled": True, "originate": True}} router_bgp["address_family_ipv4"] = { - "peer_groups": [{"name": self.shared_utils.bgp_peer_groups["ipv4_underlay_peers"]["name"], **address_family_ipv4_peer_group}], + "peer_groups": [{"name": self.inputs.bgp_peer_groups.ipv4_underlay_peers.name, **address_family_ipv4_peer_group}], } if self.shared_utils.underlay_ipv6 is True: - router_bgp["address_family_ipv6"] = {"peer_groups": [{"name": self.shared_utils.bgp_peer_groups["ipv4_underlay_peers"]["name"], "activate": True}]} + router_bgp["address_family_ipv6"] = {"peer_groups": [{"name": self.inputs.bgp_peer_groups.ipv4_underlay_peers.name, "activate": True}]} vrfs_dict = {} # Neighbor Interfaces and VRF Neighbor Interfaces - if self.shared_utils.underlay_rfc5549 is True: + if self.inputs.underlay_rfc5549 is True: neighbor_interfaces = [] for link in self._underlay_links: if link["type"] != "underlay_p2p": @@ -75,7 +75,7 @@ def router_bgp(self: AvdStructuredConfigUnderlay) -> dict | None: neighbor_interfaces.append( { "name": link["interface"], - "peer_group": self.shared_utils.bgp_peer_groups["ipv4_underlay_peers"]["name"], + "peer_group": self.inputs.bgp_peer_groups.ipv4_underlay_peers.name, "remote_as": link["peer_bgp_as"], "peer": link["peer"], "description": "_".join([link["peer"], link["peer_interface"]]), @@ -95,7 +95,7 @@ def router_bgp(self: AvdStructuredConfigUnderlay) -> dict | None: vrfs_dict[subinterface["vrf"]]["neighbor_interfaces"].append( { "name": subinterface["interface"], - "peer_group": self.shared_utils.bgp_peer_groups["ipv4_underlay_peers"]["name"], + "peer_group": self.inputs.bgp_peer_groups.ipv4_underlay_peers.name, "remote_as": link["peer_bgp_as"], # TODO: - implement some centralized way to generate these descriptions "description": f"{'_'.join([link['peer'], subinterface['peer_interface']])}_vrf_{subinterface['vrf']}", @@ -114,17 +114,17 @@ def router_bgp(self: AvdStructuredConfigUnderlay) -> dict | None: neighbor = { "ip_address": link["peer_ip_address"], - "peer_group": self.shared_utils.bgp_peer_groups["ipv4_underlay_peers"]["name"], + "peer_group": self.inputs.bgp_peer_groups.ipv4_underlay_peers.name, "remote_as": get(link, "peer_bgp_as"), "peer": link["peer"], "description": "_".join([link["peer"], link["peer_interface"]]), "bfd": get(link, "bfd"), } - if self.shared_utils.shutdown_bgp_towards_undeployed_peers is True and link["peer_is_deployed"] is False: + if self.inputs.shutdown_bgp_towards_undeployed_peers and link["peer_is_deployed"] is False: neighbor["shutdown"] = True - if self.shared_utils.underlay_filter_peer_as is True: + if self.inputs.underlay_filter_peer_as: neighbor["route_map_out"] = f"RM-BGP-AS{link['peer_bgp_as']}-OUT" append_if_not_duplicate( @@ -139,7 +139,7 @@ def router_bgp(self: AvdStructuredConfigUnderlay) -> dict | None: for subinterface in link["subinterfaces"]: neighbor = { "ip_address": subinterface["peer_ip_address"], - "peer_group": self.shared_utils.bgp_peer_groups["ipv4_underlay_peers"]["name"], + "peer_group": self.inputs.bgp_peer_groups.ipv4_underlay_peers.name, "remote_as": get(link, "peer_bgp_as"), "description": f"{'_'.join([link['peer'], subinterface['peer_interface']])}_vrf_{subinterface['vrf']}", "bfd": get(link, "bfd"), diff --git a/python-avd/pyavd/_eos_designs/structured_config/underlay/router_isis.py b/python-avd/pyavd/_eos_designs/structured_config/underlay/router_isis.py index ad1753acd2d..65e1d25e5c9 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/underlay/router_isis.py +++ b/python-avd/pyavd/_eos_designs/structured_config/underlay/router_isis.py @@ -7,7 +7,7 @@ from typing import TYPE_CHECKING from pyavd._errors import AristaAvdInvalidInputsError -from pyavd._utils import get, strip_empties_from_dict +from pyavd._utils import default, strip_empties_from_dict from .utils import UtilsMixin @@ -32,52 +32,45 @@ def router_isis(self: AvdStructuredConfigUnderlay) -> dict | None: "instance": self.shared_utils.isis_instance_name, "log_adjacency_changes": True, "net": self._isis_net, - "router_id": self.shared_utils.router_id if not self.shared_utils.use_router_general_for_router_id else None, + "router_id": self.shared_utils.router_id if not self.inputs.use_router_general_for_router_id else None, "is_type": self._is_type, - "address_family_ipv4": {"enabled": True, "maximum_paths": get(self._hostvars, "isis_maximum_paths", default=4)}, + "address_family_ipv4": {"enabled": True, "maximum_paths": self.inputs.isis_maximum_paths}, } if self.shared_utils.underlay_ldp is True: router_isis["mpls_ldp_sync_default"] = True # TI-LFA - if get(self._hostvars, "isis_ti_lfa.enabled") is True: + if self.inputs.isis_ti_lfa.enabled: router_isis["timers"] = { "local_convergence": { - "delay": get(self._hostvars, "isis_ti_lfa.local_convergence_delay", default="10000"), + "delay": self.inputs.isis_ti_lfa.local_convergence_delay, "protected_prefixes": True, }, } - ti_lfa_protection = get(self._hostvars, "isis_ti_lfa.protection") - if ti_lfa_protection == "link": - router_isis["address_family_ipv4"]["fast_reroute_ti_lfa"] = {"mode": "link-protection"} - elif ti_lfa_protection == "node": - router_isis["address_family_ipv4"]["fast_reroute_ti_lfa"] = {"mode": "node-protection"} + if self.inputs.isis_ti_lfa.protection: + router_isis["address_family_ipv4"]["fast_reroute_ti_lfa"] = {"mode": f"{self.inputs.isis_ti_lfa.protection}-protection"} # Overlay protocol if self.shared_utils.overlay_routing_protocol == "none": router_isis["redistribute_routes"] = [{"source_protocol": "connected"}] if self.shared_utils.underlay_sr is True: - router_isis["advertise"] = { - "passive_only": get(self._hostvars, "isis_advertise_passive_only", default=False), - } + router_isis["advertise"] = {"passive_only": self.inputs.isis_advertise_passive_only} # TODO: - enabling IPv6 only in SR cases as per existing behavior # but this could probably be taken out if self.shared_utils.underlay_ipv6 is True: - router_isis["address_family_ipv6"] = {"enabled": True, "maximum_paths": get(self._hostvars, "isis_maximum_paths", default=4)} - if ti_lfa_protection == "link": - router_isis["address_family_ipv6"]["fast_reroute_ti_lfa"] = {"mode": "link-protection"} - elif ti_lfa_protection == "node": - router_isis["address_family_ipv6"]["fast_reroute_ti_lfa"] = {"mode": "node-protection"} + router_isis["address_family_ipv6"] = {"enabled": True, "maximum_paths": self.inputs.isis_maximum_paths} + if self.inputs.isis_ti_lfa.protection: + router_isis["address_family_ipv6"]["fast_reroute_ti_lfa"] = {"mode": f"{self.inputs.isis_ti_lfa.protection}-protection"} router_isis["segment_routing_mpls"] = {"router_id": self.shared_utils.router_id, "enabled": True} return strip_empties_from_dict(router_isis) @cached_property def _isis_net(self: AvdStructuredConfigUnderlay) -> str | None: - if get(self._hostvars, "isis_system_id_format") == "node_id": - isis_system_id_prefix = get(self.shared_utils.switch_data_combined, "isis_system_id_prefix") + if self.inputs.isis_system_id_format == "node_id": + isis_system_id_prefix = self.shared_utils.node_config.isis_system_id_prefix if self.shared_utils.underlay_isis is True and isis_system_id_prefix is None: msg = ( f"'isis_system_id_prefix' is required when 'isis_system_id_format' is set to 'node_id'." @@ -92,16 +85,12 @@ def _isis_net(self: AvdStructuredConfigUnderlay) -> str | None: else: system_id = self.ipv4_to_isis_system_id(self.shared_utils.router_id) - isis_area_id = get(self._hostvars, "isis_area_id", default="49.0001") + isis_area_id = self.inputs.isis_area_id return f"{isis_area_id}.{system_id}.00" @cached_property def _is_type(self: AvdStructuredConfigUnderlay) -> str: - default_is_type = get(self._hostvars, "isis_default_is_type", default="level-2") - is_type = str(get(self.shared_utils.switch_data_combined, "is_type", default=default_is_type)).lower() - if is_type not in ["level-1", "level-2", "level-1-2"]: - is_type = "level-2" - return is_type + return default(self.shared_utils.node_config.is_type, self.inputs.isis_default_is_type) @staticmethod def ipv4_to_isis_system_id(ipv4_address: str) -> str: diff --git a/python-avd/pyavd/_eos_designs/structured_config/underlay/router_msdp.py b/python-avd/pyavd/_eos_designs/structured_config/underlay/router_msdp.py index 74437b785b1..8f80fc505c1 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/underlay/router_msdp.py +++ b/python-avd/pyavd/_eos_designs/structured_config/underlay/router_msdp.py @@ -6,7 +6,7 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import get, get_item +from pyavd._utils import get from pyavd.j2filters import natural_sort from .utils import UtilsMixin @@ -29,25 +29,19 @@ def router_msdp(self: AvdStructuredConfigUnderlay) -> dict | None: Used for to configure multicast anycast RPs for the underlay """ - if self.shared_utils.underlay_multicast_rps is None: + if not self.shared_utils.underlay_multicast or not self.inputs.underlay_multicast_rps: return None - if self.shared_utils.underlay_multicast_anycast_rp_mode != "msdp": + if self.inputs.underlay_multicast_anycast_rp.mode != "msdp": return None peers = set() - for rp_entry in self.shared_utils.underlay_multicast_rps: - if (nodes := get(rp_entry, "nodes")) is None or len(nodes) < 2: - continue - - if (node_entry := get_item(nodes, "name", self.shared_utils.hostname)) is None: + for rp_entry in self.inputs.underlay_multicast_rps: + if len(rp_entry.nodes) < 2 or self.shared_utils.hostname not in rp_entry.nodes: continue # Anycast-RP using MSDP - for node in nodes: - if node == node_entry: - continue - peers.add(node["name"]) + peers.update(node.name for node in rp_entry.nodes if node.name != self.shared_utils.hostname) if not peers: return None diff --git a/python-avd/pyavd/_eos_designs/structured_config/underlay/router_ospf.py b/python-avd/pyavd/_eos_designs/structured_config/underlay/router_ospf.py index 96262a333d1..8e07ef14a77 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/underlay/router_ospf.py +++ b/python-avd/pyavd/_eos_designs/structured_config/underlay/router_ospf.py @@ -6,7 +6,7 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import default, get +from pyavd._utils import default from .utils import UtilsMixin @@ -29,21 +29,19 @@ def router_ospf(self: AvdStructuredConfigUnderlay) -> dict | None: ospf_processes = [] - process_id = self.shared_utils.underlay_ospf_process_id - no_passive_interfaces = [link["interface"] for link in self._underlay_links if link["type"] == "underlay_p2p"] if self.shared_utils.mlag_l3 is True: - mlag_l3_vlan = default(self.shared_utils.mlag_peer_l3_vlan, self.shared_utils.mlag_peer_vlan) + mlag_l3_vlan = default(self.shared_utils.mlag_peer_l3_vlan, self.shared_utils.node_config.mlag_peer_vlan) no_passive_interfaces.append(f"Vlan{mlag_l3_vlan}") process = { - "id": process_id, + "id": self.inputs.underlay_ospf_process_id, "passive_interface_default": True, - "router_id": self.shared_utils.router_id if not self.shared_utils.use_router_general_for_router_id else None, - "max_lsa": get(self._hostvars, "underlay_ospf_max_lsa", default=12000), + "router_id": self.shared_utils.router_id if not self.inputs.use_router_general_for_router_id else None, + "max_lsa": self.inputs.underlay_ospf_max_lsa, "no_passive_interfaces": no_passive_interfaces, - "bfd_enable": get(self._hostvars, "underlay_ospf_bfd_enable", default=False), + "bfd_enable": self.inputs.underlay_ospf_bfd_enable, } if self.shared_utils.overlay_routing_protocol == "none": diff --git a/python-avd/pyavd/_eos_designs/structured_config/underlay/router_pim_sparse_mode.py b/python-avd/pyavd/_eos_designs/structured_config/underlay/router_pim_sparse_mode.py index deccb9d595a..67dcfc9ad6f 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/underlay/router_pim_sparse_mode.py +++ b/python-avd/pyavd/_eos_designs/structured_config/underlay/router_pim_sparse_mode.py @@ -6,7 +6,7 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import get, get_item +from pyavd._utils import get from .utils import UtilsMixin @@ -28,40 +28,36 @@ def router_pim_sparse_mode(self: AvdStructuredConfigUnderlay) -> dict | None: Used for to configure multicast RPs for the underlay """ - if self.shared_utils.underlay_multicast_rps is None: + if not self.shared_utils.underlay_multicast or not self.inputs.underlay_multicast_rps: return None rp_addresses = [] anycast_rps = [] - for rp_entry in self.shared_utils.underlay_multicast_rps: - rp_address = {"address": rp_entry["rp"]} - if rp_entry.get("groups") is not None: - if (acl := rp_entry.get("access_list_name")) is not None: - rp_address["access_lists"] = [acl] + for rp_entry in self.inputs.underlay_multicast_rps: + rp_address = {"address": rp_entry.rp} + if rp_entry.groups: + if rp_entry.access_list_name: + rp_address["access_lists"] = [rp_entry.access_list_name] else: - rp_address["groups"] = rp_entry["groups"] + rp_address["groups"] = rp_entry.groups._as_list() rp_addresses.append(rp_address) - if (nodes := get(rp_entry, "nodes")) is None or len(nodes) < 2: + if len(rp_entry.nodes) < 2 or self.shared_utils.hostname not in rp_entry.nodes or self.inputs.underlay_multicast_anycast_rp.mode != "pim": continue - if get_item(nodes, "name", self.shared_utils.hostname) is None: - continue - - if self.shared_utils.underlay_multicast_anycast_rp_mode == "pim": - # Anycast-RP using PIM (default) - anycast_rps.append( - { - "address": rp_entry["rp"], - "other_anycast_rp_addresses": [ - { - "address": get(self.shared_utils.get_peer_facts(node["name"]), "router_id", required=True), - } - for node in nodes - ], - }, - ) + # Anycast-RP using PIM (default) + anycast_rps.append( + { + "address": rp_entry.rp, + "other_anycast_rp_addresses": [ + { + "address": get(self.shared_utils.get_peer_facts(node.name), "router_id", required=True), + } + for node in rp_entry.nodes + ], + }, + ) if rp_addresses: router_pim_sparse_mode = { diff --git a/python-avd/pyavd/_eos_designs/structured_config/underlay/standard_access_lists.py b/python-avd/pyavd/_eos_designs/structured_config/underlay/standard_access_lists.py index 94550007260..12d2c4994b7 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/underlay/standard_access_lists.py +++ b/python-avd/pyavd/_eos_designs/structured_config/underlay/standard_access_lists.py @@ -26,23 +26,23 @@ def standard_access_lists(self: AvdStructuredConfigUnderlay) -> list | None: Used for to configure ACLs used by multicast RPs for the underlay """ - if self.shared_utils.underlay_multicast_rps is None: + if not self.shared_utils.underlay_multicast or not self.inputs.underlay_multicast_rps: return None standard_access_lists = [] - for rp_entry in self.shared_utils.underlay_multicast_rps: - if rp_entry.get("groups") is None or rp_entry.get("access_list_name") is None: + for rp_entry in self.inputs.underlay_multicast_rps: + if not rp_entry.groups or not rp_entry.access_list_name: continue standard_access_lists.append( { - "name": rp_entry["access_list_name"], + "name": rp_entry.access_list_name, "sequence_numbers": [ { "sequence": (index + 1) * 10, "action": f"permit {group}", } - for index, group in enumerate(rp_entry["groups"]) + for index, group in enumerate(rp_entry.groups) ], }, ) diff --git a/python-avd/pyavd/_eos_designs/structured_config/underlay/static_routes.py b/python-avd/pyavd/_eos_designs/structured_config/underlay/static_routes.py index e4b6c563eeb..e54f53638de 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/underlay/static_routes.py +++ b/python-avd/pyavd/_eos_designs/structured_config/underlay/static_routes.py @@ -6,7 +6,7 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._utils import get +from pyavd._errors import AristaAvdInvalidInputsError from .utils import UtilsMixin @@ -32,21 +32,16 @@ def static_routes(self: AvdStructuredConfigUnderlay) -> list[dict] | None: static_routes = [] for l3_interface in self.shared_utils.l3_interfaces: - if not (l3_interface_static_routes := get(l3_interface, "static_routes")): + if not l3_interface.static_routes: continue - interface_name = get(l3_interface, "name", required=True, org_key=f"...[node={self.shared_utils.hostname}].l3_interfaces[].name]") - - gateway = get( - l3_interface, - "peer_ip", - required=True, - custom_error_msg=f"Cannot set a static_route route for interface {interface_name} because 'peer_ip' is missing.", - ) + if not l3_interface.peer_ip: + msg = f"Cannot set a static_route route for interface {l3_interface.name} because 'peer_ip' is missing." + raise AristaAvdInvalidInputsError(msg) static_routes.extend( - {"destination_address_prefix": l3_interface_static_route["prefix"], "gateway": gateway} - for l3_interface_static_route in l3_interface_static_routes + {"destination_address_prefix": l3_interface_static_route.prefix, "gateway": l3_interface.peer_ip} + for l3_interface_static_route in l3_interface.static_routes ) if static_routes: diff --git a/python-avd/pyavd/_eos_designs/structured_config/underlay/utils.py b/python-avd/pyavd/_eos_designs/structured_config/underlay/utils.py index 23cdefb6516..556bc1d8dc9 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/underlay/utils.py +++ b/python-avd/pyavd/_eos_designs/structured_config/underlay/utils.py @@ -6,12 +6,14 @@ from functools import cached_property from typing import TYPE_CHECKING -from pyavd._errors import AristaAvdError +from pyavd._errors import AristaAvdError, AristaAvdMissingVariableError from pyavd._utils import default, get, get_ip_from_ip_prefix, get_item, strip_empties_from_dict from pyavd.api.interface_descriptions import InterfaceDescriptionData from pyavd.j2filters import natural_sort, range_expand if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + from . import AvdStructuredConfigUnderlay @@ -35,7 +37,7 @@ def _avd_peers(self: AvdStructuredConfigUnderlay) -> list: @cached_property def _underlay_filter_peer_as_route_maps_asns(self: AvdStructuredConfigUnderlay) -> list: """Filtered ASNs.""" - if self.shared_utils.underlay_filter_peer_as is False: + if not self.inputs.underlay_filter_peer_as: return [] # using set comprehension with `{}` to remove duplicates and then run natural_sort to convert to list. @@ -46,16 +48,16 @@ def _underlay_links(self: AvdStructuredConfigUnderlay) -> list: """Returns the list of underlay links for this device.""" underlay_links = [] underlay_links.extend(self._uplinks) - if self.shared_utils.fabric_sflow_uplinks is not None: + if self.inputs.fabric_sflow.uplinks is not None: for uplink in underlay_links: - uplink.update({"sflow": {"enable": self.shared_utils.fabric_sflow_uplinks}}) + uplink.update({"sflow": {"enable": self.inputs.fabric_sflow.uplinks}}) - uplinks_flow_tracker = self.shared_utils.get_flow_tracker(None, "uplinks") + uplinks_flow_tracker = self.shared_utils.get_flow_tracker(self.inputs.fabric_flow_tracking.uplinks) if uplinks_flow_tracker is not None: for uplink in underlay_links: - uplink.update({"flow_tracker": uplinks_flow_tracker}) + uplink["flow_tracker"] = uplinks_flow_tracker - downlinks_flow_tracker = self.shared_utils.get_flow_tracker(None, "downlinks") + downlinks_flow_tracker = self.shared_utils.get_flow_tracker(self.inputs.fabric_flow_tracking.downlinks) for peer in self._avd_peers: peer_facts = self.shared_utils.get_peer_facts(peer, required=True) @@ -86,7 +88,7 @@ def _underlay_links(self: AvdStructuredConfigUnderlay) -> list: "mlag": get(uplink, "peer_mlag"), "underlay_multicast": get(uplink, "underlay_multicast"), "ipv6_enable": get(uplink, "ipv6_enable"), - "sflow": {"enable": self.shared_utils.fabric_sflow_downlinks}, + "sflow": {"enable": self.inputs.fabric_sflow.downlinks}, "flow_tracker": downlinks_flow_tracker, "spanning_tree_portfast": get(uplink, "peer_spanning_tree_portfast"), "structured_config": get(uplink, "structured_config"), @@ -116,7 +118,7 @@ def _underlay_links(self: AvdStructuredConfigUnderlay) -> list: @cached_property def _underlay_vlan_trunk_groups(self: AvdStructuredConfigUnderlay) -> list: """Returns a list of trunk groups to configure on the underlay link.""" - if self.shared_utils.enable_trunk_groups is not True: + if self.inputs.enable_trunk_groups is not True: return [] trunk_groups = [] @@ -144,67 +146,64 @@ def _underlay_vlan_trunk_groups(self: AvdStructuredConfigUnderlay) -> list: def _uplinks(self: AvdStructuredConfigUnderlay) -> list: return get(self._hostvars, "switch.uplinks") - def _get_l3_interface_cfg(self: AvdStructuredConfigUnderlay, l3_interface: dict) -> dict | None: + def _get_l3_interface_cfg( + self: AvdStructuredConfigUnderlay, l3_interface: EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodesItem.L3InterfacesItem + ) -> dict | None: """Returns structured_configuration for one L3 interface.""" - interface_name = get(l3_interface, "name", required=True, org_key=f"...[node={self.shared_utils.hostname}].l3_interfaces[].name]") - - interface_description = l3_interface.get("description") + interface_description = l3_interface.description if not interface_description: interface_description = self.shared_utils.interface_descriptions.underlay_ethernet_interface( InterfaceDescriptionData( shared_utils=self.shared_utils, - interface=interface_name, - peer=l3_interface.get("peer"), - peer_interface=l3_interface.get("peer_interface"), - wan_carrier=l3_interface.get("wan_carrier"), - wan_circuit_id=l3_interface.get("wan_circuit_id"), + interface=l3_interface.name, + peer=l3_interface.peer, + peer_interface=l3_interface.peer_interface, + wan_carrier=l3_interface.wan_carrier, + wan_circuit_id=l3_interface.wan_circuit_id, ), ) # TODO: catch if ip_address is not valid or not dhcp - ip_address = get( - l3_interface, - "ip_address", - required=True, - org_key=f"{self.shared_utils.node_type_key_data['key']}.nodes[name={self.shared_utils.hostname}].l3_interfaces[name={interface_name}].ip_address", - ) + if not l3_interface.ip_address: + msg = f"{self.shared_utils.node_type_key_data.key}.nodes[name={self.shared_utils.hostname}].l3_interfaces[name={l3_interface.name}].ip_address" + raise AristaAvdMissingVariableError(msg) interface = { - "name": interface_name, + "name": l3_interface.name, "peer_type": "l3_interface", - "peer": l3_interface.get("peer"), - "peer_interface": l3_interface.get("peer_interface"), - "ip_address": ip_address, - "shutdown": not l3_interface.get("enabled", True), - "switchport": {"enabled": False if "." not in interface_name else None}, + "peer": l3_interface.peer, + "peer_interface": l3_interface.peer_interface, + "ip_address": l3_interface.ip_address, + "shutdown": not l3_interface.enabled, + "switchport": {"enabled": False if "." not in l3_interface.name else None}, "description": interface_description, - "speed": l3_interface.get("speed"), - "service_profile": l3_interface.get("qos_profile"), - "access_group_in": get(self._l3_interface_acls, f"{interface_name}..ipv4_acl_in..name", separator=".."), - "access_group_out": get(self._l3_interface_acls, f"{interface_name}..ipv4_acl_out..name", separator=".."), - "eos_cli": l3_interface.get("raw_eos_cli"), - "struct_cfg": l3_interface.get("structured_config"), - "flow_tracker": self.shared_utils.get_flow_tracker(l3_interface, "l3_interfaces"), + "speed": l3_interface.speed, + "service_profile": l3_interface.qos_profile, + "access_group_in": get(self._l3_interface_acls, f"{l3_interface.name}..ipv4_acl_in..name", separator=".."), + "access_group_out": get(self._l3_interface_acls, f"{l3_interface.name}..ipv4_acl_out..name", separator=".."), + "eos_cli": l3_interface.raw_eos_cli, + "struct_cfg": l3_interface.structured_config._as_dict(strip_values=()), + "flow_tracker": self.shared_utils.get_flow_tracker(l3_interface.flow_tracking), } - if self.shared_utils.fabric_sflow_l3_interfaces is not None: - interface["sflow"] = {"enable": self.shared_utils.fabric_sflow_l3_interfaces} + if self.inputs.fabric_sflow.l3_interfaces is not None: + interface["sflow"] = {"enable": self.inputs.fabric_sflow.l3_interfaces} - if "." in interface_name: - interface["encapsulation_dot1q"] = {"vlan": int(get(l3_interface, "encapsulation_dot1q_vlan", default=interface_name.split(".")[-1]))} + if "." in l3_interface.name: + interface["encapsulation_dot1q"] = {"vlan": default(l3_interface.encapsulation_dot1q_vlan, int(l3_interface.name.split(".", maxsplit=1)[-1]))} - if ip_address == "dhcp" and l3_interface.get("dhcp_accept_default_route", True): + if l3_interface.ip_address == "dhcp" and l3_interface.dhcp_accept_default_route: interface["dhcp_client_accept_default_route"] = True if ( self.shared_utils.is_wan_router - and (wan_carrier_name := l3_interface.get("wan_carrier")) is not None + and (wan_carrier_name := l3_interface.wan_carrier) is not None and interface["access_group_in"] is None - and not get(get_item(self.shared_utils.wan_carriers, "name", wan_carrier_name, default={}), "trusted") + and (wan_carrier_name not in self.inputs.wan_carriers or not self.inputs.wan_carriers[wan_carrier_name].trusted) ): msg = ( "'ipv4_acl_in' must be set on WAN interfaces where 'wan_carrier' is set, unless the carrier is configured as 'trusted' " - f"under 'wan_carriers'. 'ipv4_acl_in' is missing on interface '{interface_name}'." + f"under 'wan_carriers'. 'ipv4_acl_in' is missing on interface '{l3_interface.name}'." ) raise AristaAvdError(msg) @@ -219,11 +218,10 @@ def _get_l3_uplink_with_l2_as_subint(self: AvdStructuredConfigUnderlay, link: di interfaces = [] for tenant in self.shared_utils.filtered_tenants: - for vrf in tenant["vrfs"]: - for svi in vrf["svis"]: - svi_id = int(svi["id"]) + for vrf in tenant.vrfs: + for svi in vrf.svis: # Skip any vlans not part of the link - if svi_id not in vlans: + if svi.id not in vlans: continue interfaces.append(self._get_l2_as_subint(link, svi, vrf)) @@ -242,37 +240,41 @@ def _get_l3_uplink_with_l2_as_subint(self: AvdStructuredConfigUnderlay, link: di raise AristaAvdError(msg) return main_interface, [interface for interface in interfaces if interface["name"] != link["interface"]] - def _get_l2_as_subint(self: AvdStructuredConfigUnderlay, link: dict, svi: dict, vrf: dict) -> dict: + def _get_l2_as_subint( + self: AvdStructuredConfigUnderlay, + link: dict, + svi: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem.SvisItem, + vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem, + ) -> dict: """ Return structured config for one subinterface representing the given SVI. Only supports static IPs or VRRP. """ - svi_id = int(svi["id"]) - is_native = svi_id == link.get("native_vlan") - interface_name = link["interface"] if is_native else f"{link['interface']}.{svi_id}" + is_native = svi.id == link.get("native_vlan") + interface_name = link["interface"] if is_native else f"{link['interface']}.{svi.id}" subinterface = { "name": interface_name, "peer": link["peer"], - "peer_interface": f"{link['peer_interface']} VLAN {svi_id}", + "peer_interface": f"{link['peer_interface']} VLAN {svi.id}", "peer_type": link["peer_type"], - "description": default(svi.get("description"), svi["name"]), - "shutdown": not (svi.get("enabled", False)), + "description": default(svi.description, svi.name), + "shutdown": not default(svi.enabled, False), # noqa: FBT003 "switchport": {"enabled": False if is_native else None}, - "encapsulation_dot1q": {"vlan": None if is_native else svi_id}, - "vrf": vrf["name"] if vrf["name"] != "default" else None, - "ip_address": svi.get("ip_address"), - "ipv6_address": svi.get("ipv6_address"), - "ipv6_enable": svi.get("ipv6_enable"), - "mtu": svi.get("mtu") if self.shared_utils.platform_settings_feature_support_per_interface_mtu else None, - "eos_cli": svi.get("raw_eos_cli"), - "struct_cfg": svi.get("structured_config"), + "encapsulation_dot1q": {"vlan": None if is_native else svi.id}, + "vrf": vrf.name if vrf.name != "default" else None, + "ip_address": svi.ip_address, + "ipv6_address": svi.ipv6_address, + "ipv6_enable": svi.ipv6_enable, + "mtu": svi.mtu if self.shared_utils.platform_settings.feature_support.per_interface_mtu else None, + "eos_cli": svi.raw_eos_cli, + "struct_cfg": svi.structured_config._as_dict(strip_values=()) or None, "flow_tracker": link.get("flow_tracker"), } if (mtu := subinterface["mtu"]) is not None and subinterface["mtu"] > self.shared_utils.p2p_uplinks_mtu: msg = ( f"MTU '{self.shared_utils.p2p_uplinks_mtu}' set for 'p2p_uplinks_mtu' must be larger or equal to MTU '{mtu}' " - f"set on the SVI '{svi_id}'." + f"set on the SVI '{svi.id}'." "Either adjust the MTU on the SVI or p2p_uplinks_mtu." ) raise AristaAvdError(msg) @@ -307,30 +309,28 @@ def _l3_interface_acls(self: AvdStructuredConfigUnderlay) -> dict[str, dict[str, """ l3_interface_acls = {} for l3_interface in self.shared_utils.l3_interfaces: - ipv4_acl_in = get(l3_interface, "ipv4_acl_in") - ipv4_acl_out = get(l3_interface, "ipv4_acl_out") + ipv4_acl_in = l3_interface.ipv4_acl_in + ipv4_acl_out = l3_interface.ipv4_acl_out if ipv4_acl_in is None and ipv4_acl_out is None: continue - interface_name = l3_interface["name"] - interface_ip: str | None = l3_interface.get("dhcp_ip") if (ip_address := l3_interface.get("ip_address")) == "dhcp" else ip_address + interface_ip = l3_interface.dhcp_ip if (ip_address := l3_interface.ip_address) == "dhcp" else ip_address if interface_ip is not None and "/" in interface_ip: interface_ip = get_ip_from_ip_prefix(interface_ip) - peer_ip: str | None = get(l3_interface, "peer_ip") if ipv4_acl_in is not None: - l3_interface_acls.setdefault(interface_name, {})["ipv4_acl_in"] = self.shared_utils.get_ipv4_acl( + l3_interface_acls.setdefault(l3_interface.name, {})["ipv4_acl_in"] = self.shared_utils.get_ipv4_acl( name=ipv4_acl_in, - interface_name=interface_name, + interface_name=l3_interface.name, interface_ip=interface_ip, - peer_ip=peer_ip, - ) + peer_ip=l3_interface.peer_ip, + )._as_dict() if ipv4_acl_out is not None: - l3_interface_acls.setdefault(interface_name, {})["ipv4_acl_out"] = self.shared_utils.get_ipv4_acl( + l3_interface_acls.setdefault(l3_interface.name, {})["ipv4_acl_out"] = self.shared_utils.get_ipv4_acl( name=ipv4_acl_out, - interface_name=interface_name, + interface_name=l3_interface.name, interface_ip=interface_ip, - peer_ip=peer_ip, - ) + peer_ip=l3_interface.peer_ip, + )._as_dict() return l3_interface_acls diff --git a/python-avd/pyavd/_schema/coerce_type.py b/python-avd/pyavd/_schema/coerce_type.py new file mode 100644 index 00000000000..d071a0f7539 --- /dev/null +++ b/python-avd/pyavd/_schema/coerce_type.py @@ -0,0 +1,117 @@ +# Copyright (c) 2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + +from pyavd._schema.models.avd_base import AvdBase + +from .constants import ACCEPTED_COERCION_MAP + +if TYPE_CHECKING: + from typing import NoReturn, TypeVar + + from typing_extensions import Self + + from pyavd._schema.models.type_vars import T_AvdBase + + T = TypeVar("T") + + +def nullifiy_class(cls: type[T_AvdBase]) -> type: + """ + Returns a subclass of the given class with overrides for "null" values. + + This class is used when the input for a dict or a list is None/null/none, + to be able to signal to the deepmerge/inherit methods that this is not the same as an unset variable. + """ + + class NullifiedCls(cls): + def _get_defined_attr(self, name: str) -> T_AvdBase | None: + """ + Return the default values or None. + + This is required for the various merge / inheritance logic to always take from this if undefined. + """ + return getattr(self, name) + + def _as_dict(self, *_args: Any, **_kwargs: Any) -> None: + """Always None.""" + + def _as_list(self, *_args: Any, **_kwargs: Any) -> None: + """Always None.""" + + def __repr__(self) -> str: + return f"" + + def _deepinherited(self, *_args: Any, **_kwargs: Any) -> Self: + """Nothing to do since a NullifiedCls will override anything with None.""" + return self._deepcopy() + + def _deepinherit(self, *_args: Any, **_kwargs: Any) -> None: + """Nothing to do since a NullifiedCls will override anything with None.""" + + def _inherit(self, *_args: Any, **_kwargs: Any) -> None: + """Nothing to do since a NullifiedCls will override anything with None.""" + + def _deepmerge(self, *_args: Any, **_kwargs: Any) -> NoReturn: + msg = "A NullifiedCls cannot be inplace deepmerged. Use _deepmerged() instead." + raise NotImplementedError(msg) + + def _deepmerged(self, other: T_AvdBase, *_args: Any, **_kwargs: Any) -> T_AvdBase: + """Returning the other directly since NullifiedCls is empty.""" + return other._deepcopy() + + def _cast_as(self, new_type: type[T_AvdBase], *_args: Any, **_kwargs: Any) -> T_AvdBase: + """Wrap the new type in it's own NullifiedCls.""" + return nullifiy_class(new_type)() + + return NullifiedCls + + +def coerce_type(value: Any, target_type: type[T]) -> T: + """ + Return a coerced variant of the given value to the target_type. + + If the value is already of the correct type the value will be returned untouched. + + If coercion cannot be done this will raise a TypeError. + """ + if value is None: + if issubclass(target_type, AvdBase): + # None values are sometimes used to overwrite inherited profiles. + # This ensures we still follow the type hint of the class. + return nullifiy_class(target_type)() + + # Other None values are left untouched. + elif target_type is Any or isinstance(value, target_type): + # Avoid hitting the else block. + pass + + elif target_type in ACCEPTED_COERCION_MAP and isinstance(value, ACCEPTED_COERCION_MAP[target_type]): + try: + return target_type(value) + except ValueError as exception: + raise_coerce_error(value, target_type, exception) + + # Identify subclass of AvdModel without importing AvdModel (circular import) + elif issubclass(target_type, AvdBase): + try: + return target_type._load(data=value) + except TypeError as exception: + raise_coerce_error(value, target_type, exception) + + else: + raise_coerce_error(value, target_type) + + # All the pass brings us here to return the original value. + return value + + +def raise_coerce_error(value: Any, target_type: type, exception: Exception | None = None) -> NoReturn: + # Not possible to coerce value. + msg = f"Invalid type '{type(value)}'. Unable to coerce to type '{target_type}' for the value: {value}" + if exception is not None: + raise TypeError(msg) from exception + raise TypeError(msg) diff --git a/python-avd/pyavd/_schema/constants.py b/python-avd/pyavd/_schema/constants.py index c61cbbdabd5..58a87414956 100644 --- a/python-avd/pyavd/_schema/constants.py +++ b/python-avd/pyavd/_schema/constants.py @@ -19,3 +19,10 @@ "eos_cli_config_gen": EOS_CLI_CONFIG_GEN_PICKLED_SCHEMA_PATH, "eos_designs": EOS_DESIGNS_PICKLED_SCHEMA_PATH, } + +ACCEPTED_COERCION_MAP = { + int: (str, bool), + str: (int, bool, float), + bool: (str, int), +} +"""Map of target_types and allowed source types for automatic coercion.""" diff --git a/python-avd/pyavd/_schema/models/__init__.py b/python-avd/pyavd/_schema/models/__init__.py new file mode 100644 index 00000000000..e772bee41fe --- /dev/null +++ b/python-avd/pyavd/_schema/models/__init__.py @@ -0,0 +1,3 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. diff --git a/python-avd/pyavd/_schema/models/avd_base.py b/python-avd/pyavd/_schema/models/avd_base.py new file mode 100644 index 00000000000..22beb558607 --- /dev/null +++ b/python-avd/pyavd/_schema/models/avd_base.py @@ -0,0 +1,68 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from __future__ import annotations + +from abc import ABC, abstractmethod +from copy import deepcopy +from typing import TYPE_CHECKING, Literal + +if TYPE_CHECKING: + from collections.abc import Mapping, Sequence + + from typing_extensions import Self + + from .type_vars import T_AvdBase + + +class AvdBase(ABC): + """Base class used for schema-based data classes holding data loaded from AVD inputs.""" + + def __eq__(self, other: object) -> bool: + """Compare two instances of AvdBase by comparing their repr.""" + if isinstance(other, self.__class__): + return repr(self) == repr(other) + return False + + def _deepcopy(self) -> Self: + """Return a copy including all nested models.""" + return deepcopy(self) + + @classmethod + @abstractmethod + def _load(cls, data: Sequence | Mapping) -> Self: + """Returns a new instance loaded with the given data.""" + + @abstractmethod + def _dump(self, include_default_values: bool = False, strip_values: tuple = (None, [], {})) -> dict | list: + """Dump data into native Python types with or without default values.""" + + @abstractmethod + def _cast_as(self, new_type: type[T_AvdBase], ignore_extra_keys: bool = False) -> T_AvdBase: + """Recast a class instance as another similar subclass if they are compatible.""" + + @abstractmethod + def _deepmerge(self, other: Self, list_merge: Literal["append", "replace"] = "append") -> None: + """ + Update instance by deepmerging the other instance in. + + Args: + other: The other instance of the same type to merge on this instance. + list_merge: Merge strategy used on any nested lists. + - "append" will first try to deep merge on the primary key, and if not found it will append non-existing items. + - "replace" will replace the full list. + """ + + def _deepmerged(self, other: Self, list_merge: Literal["append", "replace"] = "append") -> Self: + """ + Return new instance with the result of the deepmerge of "other" on this instance. + + Args: + other: The other instance of the same type to merge on this instance. + list_merge: Merge strategy used on any nested lists. + - "append" will first try to deep merge on the primary key, and if not found it will append non-existing items. + - "replace" will replace the full list. + """ + new_instance = deepcopy(self) + new_instance._deepmerge(other=other, list_merge=list_merge) + return new_instance diff --git a/python-avd/pyavd/_schema/models/avd_indexed_list.py b/python-avd/pyavd/_schema/models/avd_indexed_list.py new file mode 100644 index 00000000000..b2e43f5e651 --- /dev/null +++ b/python-avd/pyavd/_schema/models/avd_indexed_list.py @@ -0,0 +1,198 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from __future__ import annotations + +import re +from collections.abc import Iterable, Iterator, Sequence +from copy import deepcopy +from typing import TYPE_CHECKING, ClassVar, Generic, Literal + +from pyavd._schema.coerce_type import coerce_type +from pyavd._utils import Undefined, UndefinedType + +from .avd_base import AvdBase +from .type_vars import T_AvdModel, T_PrimaryKey + +if TYPE_CHECKING: + from typing_extensions import Self + + from .avd_model import AvdModel + from .type_vars import T, T_AvdIndexedList + +NATURAL_SORT_PATTERN = re.compile(r"(\d+)") + + +class AvdIndexedList(Sequence[T_AvdModel], Generic[T_PrimaryKey, T_AvdModel], AvdBase): + """ + Base class used for schema-based data classes holding lists-of-dictionaries-with-primary-key loaded from AVD inputs. + + Other lists are *not* using this model. + """ + + _item_type: ClassVar[type[AvdModel]] + """Type of items. This is used instead of inspecting the type-hints to improve performance significantly.""" + _primary_key: ClassVar[str] + """The name of the primary key to be used in the items.""" + _items: dict[T_PrimaryKey, T_AvdModel] + """ + Internal attribute holding the actual data. Using a dict keyed by the primary key value of each item to improve performance + significantly when searching for a specific item. + """ + + @classmethod + def _load(cls, data: Sequence) -> Self: + """Returns a new instance loaded with the data from the given list.""" + return cls._from_list(data) + + @classmethod + def _from_list(cls, data: Sequence) -> Self: + """Returns a new instance loaded with the data from the given list.""" + if not isinstance(data, Sequence): + msg = f"Expecting 'data' as a 'Sequence' when loading data into '{cls.__name__}'. Got '{type(data)}" + raise TypeError(msg) + + cls_items = [coerce_type(item, cls._item_type) for item in data] + return cls(cls_items) + + def __init__(self, items: Iterable[T_AvdModel] | UndefinedType = Undefined) -> None: + """ + AvdIndexedList subclass. + + Args: + items: Iterable holding items of the correct type to be loaded into the indexed list. + """ + if isinstance(items, UndefinedType): + self._items = {} + else: + self._items = {getattr(item, self._primary_key): item for item in items} + + def __repr__(self) -> str: + """Returns a repr with all the items including any nested models.""" + cls_name = self.__class__.__name__ + attrs = [f"{item!r}" for item in (self._items.values())] + return f"<{cls_name}([{', '.join(attrs)}])>" + + def __bool__(self) -> bool: + """Boolean check on the class to quickly determine if any items are set.""" + return bool(self._items) + + def __len__(self) -> int: + return len(self._items) + + def __contains__(self, key: T_PrimaryKey) -> bool: + return key in self._items + + def __iter__(self) -> Iterator[T_AvdModel]: + return iter(self._items.values()) + + def __getitem__(self, key: T_PrimaryKey) -> T_AvdModel: + return self._items[key] + + def __setitem__(self, key: T_PrimaryKey, value: T_AvdModel) -> None: + self._items[key] = value + + def get(self, key: T_PrimaryKey, default: T | UndefinedType = Undefined) -> T_AvdModel | T | UndefinedType: + return self._items.get(key, default) + + def items(self) -> Iterable[tuple[T_PrimaryKey, T_AvdModel]]: + return self._items.items() + + def keys(self) -> Iterable[T_PrimaryKey]: + return self._items.keys() + + def values(self) -> Iterable[T_AvdModel]: + return self._items.values() + + def append(self, item: T_AvdModel) -> None: + self._items[getattr(item, self._primary_key)] = item + + def extend(self, items: Iterable[T_AvdModel]) -> None: + self._items.update({getattr(item, self._primary_key): item for item in items}) + + def _as_list(self, include_default_values: bool = False, strip_values: tuple = (None, [], {})) -> list[dict]: + """Returns a list with all the data from this model and any nested models.""" + return [ + value + for item in self._items.values() + if (value := item._as_dict(include_default_values=include_default_values, strip_values=strip_values)) not in strip_values + ] + + def _dump(self, include_default_values: bool = False, strip_values: tuple = (None, [], {})) -> list[dict]: + return self._as_list(include_default_values=include_default_values, strip_values=strip_values) + + def _natural_sorted(self, ignore_case: bool = True) -> Self: + """Return new instance where the items are natural sorted by primary key.""" + + def convert(text: str) -> int | str: + if text.isdigit(): + return int(text) + return text.lower() if ignore_case else text + + def key(value: T_AvdModel) -> list[int | str]: + primary_key = getattr(value, self._primary_key) + return [convert(c) for c in re.split(NATURAL_SORT_PATTERN, str(primary_key))] + + cls = type(self) + return cls(sorted(self.values(), key=key)) + + def _deepmerge(self, other: Self, list_merge: Literal["append", "replace"] = "append") -> None: + """ + Update instance by deepmerging the other instance in. + + Args: + other: The other instance of the same type to merge into this instance. + list_merge: Merge strategy used on this and any nested lists. + - "append" will first try to deep merge on the primary key, and if not found it will append non-existing items. + - "replace" will replace the full list. + """ + cls = type(self) + if not isinstance(other, cls): + msg = f"Unable to merge type '{type(other)}' into '{cls}'" + raise TypeError(msg) + + if list_merge == "replace": + self._items = deepcopy(other._items) + return + + for primary_key, new_item in other.items(): + old_value = self.get(primary_key) + if old_value is Undefined or not isinstance(old_value, type(new_item)): + # New item or different type so we can just replace + self[primary_key] = deepcopy(new_item) + continue + + # Existing item of same type, so deepmerge. + self[primary_key]._deepmerge(new_item, list_merge=list_merge) + + def _deepinherit(self, other: Self) -> None: + """Update instance by recursively inheriting from other instance for all existing items. New items are *not* added.""" + cls = type(self) + if not isinstance(other, cls): + msg = f"Unable to inherit from type '{type(other)}' into '{cls}'" + raise TypeError(msg) + + for primary_key, new_item in other.items(): + old_value = self.get(primary_key) + if old_value is Undefined: + # New item so we can just append + self[primary_key] = deepcopy(new_item) + continue + + # Existing item, so deepinherit. + self[primary_key]._deepinherit(new_item) + + def _cast_as(self, new_type: type[T_AvdIndexedList], ignore_extra_keys: bool = False) -> T_AvdIndexedList: + """ + Recast a class instance as another AvdIndexedList subclass if they are compatible. + + The classes are compatible if the items of the new class is a superset of the current class. + + Useful when inheriting from profiles. + """ + cls = type(self) + if not issubclass(new_type, AvdIndexedList): + msg = f"Unable to cast '{cls}' as type '{new_type}' since '{new_type}' is not an AvdIndexedList subclass." + raise TypeError(msg) + + return new_type([item._cast_as(new_type._item_type, ignore_extra_keys=ignore_extra_keys) for item in self]) diff --git a/python-avd/pyavd/_schema/models/avd_list.py b/python-avd/pyavd/_schema/models/avd_list.py new file mode 100644 index 00000000000..51266627969 --- /dev/null +++ b/python-avd/pyavd/_schema/models/avd_list.py @@ -0,0 +1,184 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from __future__ import annotations + +import re +from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence +from copy import deepcopy +from typing import TYPE_CHECKING, Any, ClassVar, Generic, Literal + +from pyavd._schema.coerce_type import coerce_type +from pyavd._utils import Undefined, UndefinedType + +from .avd_base import AvdBase +from .avd_model import AvdModel +from .type_vars import T, T_AvdList, T_ItemType + +if TYPE_CHECKING: + from typing_extensions import Self + +NATURAL_SORT_PATTERN = re.compile(r"(\d+)") + + +class AvdList(Sequence[T_ItemType], Generic[T_ItemType], AvdBase): + """ + Base class used for schema-based data classes holding lists-of-dictionaries-with-primary-key loaded from AVD inputs. + + Other lists are *not* using this model. + """ + + _item_type: ClassVar[type] + """Type of items. This is used instead of inspecting the type-hints to improve performance significantly.""" + _items: list[T_ItemType] + """ + Internal attribute holding the actual data. Using a dict keyed by the primary key value of each item to improve performance + significantly when searching for a specific item. + """ + + @classmethod + def _load(cls, data: Sequence) -> Self: + """Returns a new instance loaded with the data from the given list.""" + return cls._from_list(data) + + @classmethod + def _from_list(cls, data: Sequence) -> Self: + """Returns a new instance loaded with the data from the given list.""" + if not isinstance(data, Sequence): + msg = f"Expecting 'data' as a 'Sequence' when loading data into '{cls.__name__}'. Got '{type(data)}" + raise TypeError(msg) + + item_type = cls._item_type + if item_type is Any: + return cls(data) + + cls_items = [coerce_type(item, item_type) for item in data] + return cls(cls_items) + + def __init__(self, items: Iterable[T_ItemType] | UndefinedType = Undefined) -> None: + """ + AvdIndexedList subclass. + + Args: + items: Iterable holding items of the correct type to be loaded into the indexed list. + """ + if isinstance(items, UndefinedType): + self._items = [] + else: + self._items = list(items) + + def __repr__(self) -> str: + """Returns a repr with all the items including any nested models.""" + cls_name = self.__class__.__name__ + items = [f"{item!r}" for item in (self._items)] + return f"<{cls_name}([{', '.join(items)}])>" + + def __bool__(self) -> bool: + """Boolean check on the class to quickly determine if any items are set.""" + return bool(self._items) + + def __len__(self) -> int: + return len(self._items) + + def __contains__(self, item: T_ItemType) -> bool: + return item in self._items + + def __iter__(self) -> Iterator[T_ItemType]: + return iter(self._items) + + def __getitem__(self, index: int) -> T_ItemType: + return self._items[index] + + def __setitem__(self, index: int, value: T_ItemType) -> None: + self._items[index] = value + + def get(self, index: int, default: T | UndefinedType = Undefined) -> T_ItemType | T | UndefinedType: + return self._items[index] if index < len(self._items) else default + + def append(self, item: T_ItemType) -> None: + self._items.append(item) + + def extend(self, items: Iterable[T_ItemType]) -> None: + self._items.extend(items) + + def _as_list(self, include_default_values: bool = False, strip_values: tuple = (None, [], {})) -> list: + """Returns a list with all the data from this model and any nested models.""" + if issubclass(self._item_type, AvdBase): + items: list[AvdBase] = self._items + return [ + value for item in items if (value := item._dump(include_default_values=include_default_values, strip_values=strip_values)) not in strip_values + ] + return [item for item in self._items if item not in strip_values] + + def _dump(self, include_default_values: bool = False, strip_values: tuple = (None, [], {})) -> list: + return self._as_list(include_default_values=include_default_values, strip_values=strip_values) + + def _natural_sorted(self, sort_key: str | None = None, ignore_case: bool = True) -> Self: + """Return new instance where the items are natural sorted by the given sort key or by the item itself.""" + + def convert(text: str) -> int | str: + if text.isdigit(): + return int(text) + return text.lower() if ignore_case else text + + def key(value: T_ItemType) -> list[int | str]: + if sort_key is not None: + if isinstance(value, AvdModel): + sort_value = str(value._get(sort_key, default=value)) + elif isinstance(value, Mapping): + sort_value = str(value.get(sort_key, value)) + else: + sort_value = str(value) + return [convert(c) for c in re.split(NATURAL_SORT_PATTERN, sort_value)] + + cls = type(self) + return cls(sorted(self._items, key=key)) + + def _filtered(self, function: Callable[[T_ItemType], bool]) -> Self: + cls = type(self) + return cls(filter(function, self._items)) + + def _deepmerge(self, other: Self, list_merge: Literal["append", "replace"] = "append") -> None: + """ + Update instance by appending or replacing the items from the other instance. + + Args: + other: The other instance of the same type to merge into this instance. + list_merge: Merge strategy used on this and any nested lists. + - "append" will first try to deep merge on the primary key, and if not found it will append non-existing items. + - "replace" will replace the full list. + """ + cls = type(self) + if not isinstance(other, cls): + msg = f"Unable to merge type '{type(other)}' into '{cls}'" + raise TypeError(msg) + + if list_merge == "replace": + self._items = deepcopy(other._items) + return + + # Append non-existing items. + self._items.extend(deepcopy([new_item for new_item in other._items if new_item not in self._items])) + + def _cast_as(self, new_type: type[T_AvdList], ignore_extra_keys: bool = False) -> T_AvdList: + """ + Recast a class instance as another AvdList subclass if they are compatible. + + The classes are compatible if the items of the new class is a superset of the current class. + + Useful when inheriting from profiles. + """ + cls = type(self) + if not issubclass(new_type, AvdList): + msg = f"Unable to cast '{cls}' as type '{new_type}' since '{new_type}' is not an AvdList subclass." + raise TypeError(msg) + + if issubclass(self._item_type, AvdBase): + items: list[AvdBase] = self._items + return new_type([item._cast_as(new_type._item_type, ignore_extra_keys=ignore_extra_keys) for item in items]) + + if self._item_type != new_type._item_type: + msg = f"Unable to cast '{cls}' as type '{new_type}' since they have incompatible item types." + raise TypeError(msg) + + return new_type(self._items) diff --git a/python-avd/pyavd/_schema/models/avd_model.py b/python-avd/pyavd/_schema/models/avd_model.py new file mode 100644 index 00000000000..c425e51708d --- /dev/null +++ b/python-avd/pyavd/_schema/models/avd_model.py @@ -0,0 +1,356 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from __future__ import annotations + +from collections.abc import Mapping +from copy import deepcopy +from typing import TYPE_CHECKING, Any, ClassVar, Literal + +from pyavd._schema.coerce_type import coerce_type +from pyavd._utils import Undefined, UndefinedType, merge + +from .avd_base import AvdBase +from .avd_indexed_list import AvdIndexedList + +if TYPE_CHECKING: + from typing_extensions import Self + + from .type_vars import T_AvdModel + + +class AvdModel(AvdBase): + """Base class used for schema-based data classes holding dictionaries loaded from AVD inputs.""" + + _allow_other_keys: ClassVar[bool] = False + """Attribute telling if this class should fail or ignore unknown keys found during loading in _from_dict().""" + _fields: ClassVar[dict[str, dict]] + """ + Metadata serving as a shortcut for knowing the expected type of each field and default value. + This is used instead of inspecting the type-hints to improve performance significantly. + """ + _field_to_key_map: ClassVar[dict[str, str]] = {} + """Map of field name to original dict key. Used when fields have the field_ prefix to get the original key.""" + _key_to_field_map: ClassVar[dict[str, str]] = {} + """Map of dict key to field name. Used when the key is names with a reserved keyword or mixed case. E.g. `Vxlan1` or `as`.""" + + @classmethod + def _load(cls, data: Mapping) -> Self: + """Returns a new instance loaded with the data from the given dict.""" + return cls._from_dict(data) + + @classmethod + def _from_dict(cls: type[T_AvdModel], data: Mapping, keep_extra_keys: bool = False) -> T_AvdModel: + """ + Returns a new instance loaded with the data from the given dict. + + TODO: AVD6.0.0 remove the keep_extra_keys option so we no longer support custom keys without _ in structured config. + """ + if not isinstance(data, Mapping): + msg = f"Expecting 'data' as a 'Mapping' when loading data into '{cls.__name__}'. Got '{type(data)}" + raise TypeError(msg) + + has_custom_data = "_custom_data" in cls._fields + cls_args = {} + + for key in data: + if not (field := cls._get_field_name(key)): + if keep_extra_keys or (has_custom_data and str(key).startswith("_")): + cls_args.setdefault("_custom_data", {})[key] = data[key] + continue + + if cls._allow_other_keys: + # Ignore unknown keys. + continue + + msg = f"Invalid key '{key}'. Not available on '{cls.__name__}'." + raise KeyError(msg) + + cls_args[field] = coerce_type(data[key], cls._fields[field]["type"]) + + return cls(**cls_args) + + @classmethod + def _get_field_name(cls, key: str) -> str | None: + """Returns the field name for the given key. Returns None if the key is not matching a valid field.""" + field_name = cls._key_to_field_map.get(key, key) + return field_name if field_name in cls._fields else None + + @classmethod + def _get_field_default_value(cls, name: str) -> Any: + """ + Returns the default value for a field. + + We check for a default value in the _fields information and if something is there we return that. + - For dicts, AvdModel and lists of AvdModels subclasses the default value is a callable to generate a new instance to avoid reusing a mutable object. + - For lists of simple types like 'list[str]' the default value is a list that is copied to avoid reusing a mutable object. + - For other types, which are immutable, the default value is taken directly. + + If there is no default value in the field info, we return the default-default depending on type. + - For lists and dicts we return new empty list / dict. + - For AvdModel subclasses we return a new empty instance of the class. + - For other types we return None. + """ + if name not in cls._fields: + msg = f"'{cls.__name__}' object has no attribute '{name}'" + raise AttributeError(msg) + field_info = cls._fields[name] + field_type: type = field_info["type"] + + if issubclass(field_type, AvdBase) or field_type is dict: + return default_function(field_type) if (default_function := field_info.get("default")) else field_type() + + return field_info.get("default") + + def __init__(self, **kwargs: Any) -> None: + """ + Runtime init without specific kwargs and type hints. + + Only walking the given kwargs improves performance compared to having named kwargs. + + This method is typically overridden when TYPE_HINTING is True, to provider proper suggestions and type hints for the arguments. + """ + [setattr(self, arg, arg_value) for arg, arg_value in kwargs.items() if arg_value is not Undefined] + + def __getattr__(self, name: str) -> Any: + """ + Resolves the default value for a field, set the default value on the attribute and return the value. + + We only get here if the attribute is not set already, and next call will skip this since the attribute is set. + """ + if name not in self._fields: + msg = f"'{type(self).__name__}' object has no attribute '{name}'" + raise AttributeError(msg) + + default_value = self._get_field_default_value(name) + setattr(self, name, default_value) + return default_value + + def _get_defined_attr(self, name: str) -> Any | UndefinedType: + """ + Get attribute or Undefined. + + Avoids the overridden __getattr__ to avoid default values. + """ + if name not in self._fields: + msg = f"'{type(self).__name__}' object has no attribute '{name}'" + raise AttributeError(msg) + try: + return self.__getattribute__(name) + except AttributeError: + return Undefined + + def __repr__(self) -> str: + """Returns a repr with all the fields that are set including any nested models.""" + cls_name = self.__class__.__name__ + attrs = [f"{key}={getattr(self, key)!r}" for key in self._fields if self._get_defined_attr(key) is not Undefined] + return f"<{cls_name}({', '.join(attrs)})>" + + def __bool__(self) -> bool: + """ + Boolean check on the class to quickly determine if any parameter is set. + + Note that a falsy value will still make this True. + + The check ignores the default values and is performed recursively on any nested models. + """ + return any( + # False if item is Undefined + (value := self._get_defined_attr(field)) is not Undefined + and + # False if it is AVD class with a falsy value + # True otherwise + not (isinstance(value, AvdBase) and not value) + for field in self._fields + ) + + def _as_dict(self, include_default_values: bool = False, strip_values: tuple = (None, [], {})) -> dict: + """ + Returns a dict with all the data from this model and any nested models. + + Filtered for nested None, {} and [] values. + """ + as_dict = {} + for field, field_info in self._fields.items() or (): + if (value := self._get_defined_attr(field)) is Undefined: + if not include_default_values: + continue + + value = self._get_field_default_value(field) + + if field == "_custom_data" and isinstance(value, dict) and value: + as_dict.update(value) + continue + + # Removing field_ prefix if needed. + key = self._field_to_key_map.get(field, field) + + if issubclass(field_info["type"], AvdBase) and isinstance(value, AvdBase): + value = value._dump(include_default_values=include_default_values, strip_values=strip_values) + + if value in strip_values: + continue + + as_dict[key] = value + + return as_dict + + def _dump(self, include_default_values: bool = False, strip_values: tuple = (None, [], {})) -> dict: + return self._as_dict(include_default_values=include_default_values, strip_values=strip_values) + + def _get(self, name: str, default: Any = None) -> Any: + """ + Behave like dict.get() to get a field value only if set. + + If the field balue is not set, this will not insert a default schema values but will instead return the given 'default' value (or None). + """ + if (value := self._get_defined_attr(name)) is Undefined: + return default + return value + + def _update(self, other: Self) -> None: + """Update instance by shallow merging the other instance in.""" + cls = type(self) + if not isinstance(other, cls): + msg = f"Unable to merge type '{type(other)}' into '{cls}'" + raise TypeError(msg) + + for field in cls._fields: + if new_value := other._get_defined_attr(field) is Undefined: + continue + old_value = self._get_defined_attr(field) + if old_value == new_value: + continue + setattr(self, field, new_value) + + def _deepmerge(self, other: Self, list_merge: Literal["append", "replace"] = "append") -> None: + """ + Update instance by deepmerging the other instance in. + + Args: + other: The other instance of the same type to merge on this instance. + list_merge: Merge strategy used on any nested lists. + - "append" will first try to deep merge on the primary key, and if not found it will append non-existing items. + - "replace" will replace the full list. + """ + cls = type(self) + if not isinstance(other, cls): + msg = f"Unable to merge type '{type(other)}' into '{cls}'" + raise TypeError(msg) + + for field, field_info in cls._fields.items(): + if (new_value := other._get_defined_attr(field)) is Undefined: + continue + old_value = self._get_defined_attr(field) + if old_value == new_value: + continue + + if not isinstance(old_value, type(new_value)): + # Different type so we can just replace + setattr(self, field, deepcopy(new_value)) + continue + + # Merge new value + field_type = field_info["type"] + if issubclass(field_type, AvdBase) and isinstance(old_value, field_type): + # Merge in to the existing object + old_value._deepmerge(new_value, list_merge=list_merge) + continue + + if field_type is dict: + # In-place deepmerge in to the existing dict without schema. + # Deepcopying since merge() does not copy. + merge(old_value, deepcopy(new_value), list_merge=list_merge) + continue + + setattr(self, field, new_value) + + def _inherit(self, other: Self) -> None: + """Update unset fields on this instance with fields from other instance. No merging.""" + cls = type(self) + if not isinstance(other, cls): + msg = f"Unable to inherit from type '{type(other)}' into '{cls}'" + raise TypeError(msg) + + for field in cls._fields: + if self._get_defined_attr(field) is not Undefined: + continue + if (new_value := other._get_defined_attr(field)) is Undefined: + continue + + setattr(self, field, deepcopy(new_value)) + + def _deepinherit(self, other: Self) -> None: + """Update instance by recursively inheriting unset fields from other instance. Lists are not merged.""" + cls = type(self) + if not isinstance(other, cls): + msg = f"Unable to inherit from type '{type(other)}' into '{cls}'" + raise TypeError(msg) + + for field, field_info in cls._fields.items(): + if (new_value := other._get_defined_attr(field)) is Undefined: + continue + old_value = self._get_defined_attr(field) + if old_value == new_value: + continue + + # Inherit the field only if the old value is Undefined. + if old_value is Undefined: + setattr(self, field, deepcopy(new_value)) + continue + + # Merge new value if it is a class with inheritance support. + field_type = field_info["type"] + if issubclass(field_type, (AvdModel, AvdIndexedList)) and isinstance(old_value, field_type): + # Inherit into the existing object. + old_value._deepinherit(new_value) + continue + + if field_type is dict: + # In-place deepmerge in to the existing dict without schema. + # Deepcopying since merge() does not copy. + merge(old_value, deepcopy(new_value), list_merge="replace") + + def _deepinherited(self, other: Self) -> Self: + """Return new instance with the result of recursively inheriting unset fields from other instance. Lists are not merged.""" + new_instance = deepcopy(self) + new_instance._deepinherit(other=other) + return new_instance + + def _cast_as(self, new_type: type[T_AvdModel], ignore_extra_keys: bool = False) -> T_AvdModel: + """ + Recast a class instance as another AvdModel subclass if they are compatible. + + The classes are compatible if the fields of the new class is a superset of the current class. + Unset fields are ignored when evaluating compatibility. + + Useful when inheriting from profiles. + """ + cls = type(self) + if not issubclass(new_type, AvdModel): + msg = f"Unable to cast '{cls}' as type '{new_type}' since '{new_type}' is not an AvdModel subclass." + raise TypeError(msg) + + new_args = {} + for field, field_info in cls._fields.items(): + if (value := self._get_defined_attr(field)) is Undefined: + continue + if field not in new_type._fields: + if ignore_extra_keys: + continue + msg = f"Unable to cast '{cls}' as type '{new_type}' since the field '{field}' is missing from the new class. " + raise TypeError(msg) + if field_info != new_type._fields[field]: + if issubclass(field_info["type"], (AvdBase)) and isinstance(value, (AvdBase)): + # TODO: Consider using the TypeError we raise below to ensure we know the outer type. + # TODO: with suppress(TypeError): + new_args[field] = value._cast_as(new_type._fields[field]["type"], ignore_extra_keys=ignore_extra_keys) + continue + + msg = f"Unable to cast '{cls}' as type '{new_type}' since the field '{field}' is incompatible. Value {value}" + raise TypeError(msg) + + new_args[field] = value + continue + + return new_type(**new_args) diff --git a/python-avd/pyavd/_schema/models/eos_cli_config_gen_root_model.py b/python-avd/pyavd/_schema/models/eos_cli_config_gen_root_model.py new file mode 100644 index 00000000000..12fb4824df7 --- /dev/null +++ b/python-avd/pyavd/_schema/models/eos_cli_config_gen_root_model.py @@ -0,0 +1,29 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from __future__ import annotations + +from typing import TYPE_CHECKING + +from .avd_model import AvdModel + +if TYPE_CHECKING: + from collections.abc import Mapping + + from typing_extensions import Self + + +class EosCliConfigGenRootModel(AvdModel): + @classmethod + def _from_dict(cls, data: Mapping, keep_extra_keys: bool = True) -> Self: + """ + Returns a new instance loaded with the data from the given dict. + + Args: + data: A mapping containing the EosDesigns input data to be loaded. + keep_extra_keys: Store all unknown keys in the _custom_data dict and include it again in the output of _to_dict(). + By default _all_ keys will be stored. Setting this to False will only store keys starting with _. + + TODO: AVD6.0.0 remove the keep_extra_keys option so we no longer support custom keys without _ in structured config + """ + return super()._from_dict(data, keep_extra_keys=keep_extra_keys) diff --git a/python-avd/pyavd/_schema/models/eos_designs_root_model.py b/python-avd/pyavd/_schema/models/eos_designs_root_model.py new file mode 100644 index 00000000000..a404cb3da92 --- /dev/null +++ b/python-avd/pyavd/_schema/models/eos_designs_root_model.py @@ -0,0 +1,116 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from __future__ import annotations + +from collections import ChainMap +from collections.abc import Iterator, Mapping +from typing import TYPE_CHECKING + +from pyavd._eos_cli_config_gen.schema import EosCliConfigGen +from pyavd._schema.store import create_store +from pyavd._schema.utils import get_instance_with_defaults +from pyavd._utils import get_all + +from .avd_list import AvdList +from .avd_model import AvdModel + +if TYPE_CHECKING: + from pyavd._eos_designs.schema import EosDesigns + +SKIP_KEYS = ["custom_structured_configuration_list_merge", "custom_structured_configuration_prefix"] + + +class EosDesignsRootModel(AvdModel): + @classmethod + def _from_dict(cls: type[EosDesigns], data: Mapping, keep_extra_keys: bool = False, load_custom_structured_config: bool = True) -> EosDesigns: + """ + Returns a new instance loaded with the data from the given dict. + + The EosDesignsRootModel is special because it will also load "dynamic keys" like `node_type_keys` and `network_services_keys` and + `connected_endpoints_keys`. Those models will be parsed and all mentioned keys will be searched for in the input and loaded into the + corresponding model under `_dynamic_keys`. + + Furthermore the EosDesignsRootModel will also load `custom_structured_configuration_prefix` and search for any keys prefixed with those. Found keys + will be loaded into the `_custom_structured_configurations` model. + + Args: + data: A mapping containing the EosDesigns input data to be loaded. + keep_extra_keys: Store all unknown keys in the _custom_data dict and include it again in the output of _to_dict(). + By default only keys starting with _ will be stored in _custom_data. This will change the behavior to store _all_ keys. + load_custom_structured_config: Some custom structured config contains inline Jinja templates relying on variables produced by EosDesignsFacts. + To avoid such templates breaking the type checks, we can skip loading custom_structured_configuration during the facts phase by setting this + to False. + + TODO: AVD6.0.0 remove the keep_extra_keys option so we no longer support custom keys without _ in structured config + """ + if not isinstance(data, Mapping): + msg = f"Expecting 'data' as a 'Mapping' when loading data into '{cls.__name__}'. Got '{type(data)}" + raise TypeError(msg) + + root_data = {"_dynamic_keys": cls._get_dynamic_keys(data)} + if load_custom_structured_config: + root_data["_custom_structured_configurations"] = cls._CustomStructuredConfigurations(cls._get_csc_items(data)) + + return super()._from_dict(ChainMap(root_data, data), keep_extra_keys=keep_extra_keys) + + @classmethod + def _get_csc_items(cls: type[EosDesigns], data: Mapping) -> Iterator[EosDesigns._CustomStructuredConfigurationsItem]: + """ + Returns a list of _CustomStructuredConfigurationsItem objects containing each custom structured configuration extracted from the inputs. + + Find any keys starting with any prefix defined under "custom_structured_configuration_prefix". + """ + prefixes = data.get("custom_structured_configuration_prefix", cls._get_field_default_value("custom_structured_configuration_prefix")) + if not isinstance(prefixes, (list, AvdList)): + # Invalid prefix format. + return + + for prefix in prefixes: + if not isinstance(prefix, str): + # Invalid prefix format. + continue + + if not (matching_keys := [key for key in data if str(key).startswith(prefix) and key not in SKIP_KEYS]): + continue + + prefix_length = len(prefix) + for key in matching_keys: + yield cls._CustomStructuredConfigurationsItem(key=key, value=EosCliConfigGen._from_dict({key[prefix_length:]: data[key]})) + + @classmethod + def _get_dynamic_keys(cls: type[EosDesigns], data: Mapping) -> EosDesigns._DynamicKeys: + """ + Returns the DynamicKeys object which holds a list for each dynamic key. + + The lists contain an entry for each dynamic key found in the inputs and the content of that key conforming to the schema. + + The corresponding data models are auto created by the conversion from schemas, which also sets "_dynamic_key_maps" on the class: + ```python + _dynamic_key_maps: list[dict] = [{"dynamic_keys_path": "connected_endpoints_keys.key", "model_key": "connected_endpoints_keys"}, ...] + ``` + + Here we parse "_dynamic_key_maps" and for entry find all values for the dynamic_keys_path (ex "node_type_keys.key") in the input data + to identify all dynamic keys (ex "l3leaf", "spine" ...) + """ + schema = create_store(load_from_yaml=False)["eos_designs"] + + dynamic_keys_dict = {} + + for dynamic_key_map in cls._DynamicKeys._dynamic_key_maps: + dynamic_keys_path: str = dynamic_key_map["dynamic_keys_path"] + model_key_list: list = dynamic_keys_dict.setdefault(dynamic_key_map["model_key"], []) + + # TODO: Improve the fetch of default. We need to store the default value somewhere, since this is executed before __init__ of EosDesigns. + data_with_default = get_instance_with_defaults(data, dynamic_keys_path, schema) + dynamic_keys = get_all(data_with_default, dynamic_keys_path) + for dynamic_key in dynamic_keys: + # dynamic_key is one key like "l3leaf". + if (value := data.get(dynamic_key)) is None: + # Do not add missing key or None. + continue + + model_key_list.append({"key": dynamic_key, "value": value}) + + # TODO: Just create to proper data models instead of using coerce type. + return cls._DynamicKeys._from_dict(dynamic_keys_dict) diff --git a/python-avd/pyavd/_schema/models/type_vars.py b/python-avd/pyavd/_schema/models/type_vars.py new file mode 100644 index 00000000000..aaa7189c9d3 --- /dev/null +++ b/python-avd/pyavd/_schema/models/type_vars.py @@ -0,0 +1,20 @@ +# Copyright (c) 2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from __future__ import annotations + +from typing import TYPE_CHECKING, TypeVar + +if TYPE_CHECKING: + from .avd_base import AvdBase + from .avd_indexed_list import AvdIndexedList + from .avd_list import AvdList + from .avd_model import AvdModel + +T = TypeVar("T") +T_AvdBase = TypeVar("T_AvdBase", bound="AvdBase") +T_AvdModel = TypeVar("T_AvdModel", bound="AvdModel") +T_AvdIndexedList = TypeVar("T_AvdIndexedList", bound="AvdIndexedList") +T_AvdList = TypeVar("T_AvdList", bound="AvdList") +T_PrimaryKey = TypeVar("T_PrimaryKey", int, str) +T_ItemType = TypeVar("T_ItemType") diff --git a/python-avd/pyavd/_utils/__init__.py b/python-avd/pyavd/_utils/__init__.py index 285dae80421..fb17ba5c445 100644 --- a/python-avd/pyavd/_utils/__init__.py +++ b/python-avd/pyavd/_utils/__init__.py @@ -12,7 +12,7 @@ from .get_ip_from_ip_prefix import get_ip_from_ip_prefix from .get_ip_from_pool import get_ip_from_pool from .get_item import get_item -from .groupby import groupby +from .groupby import groupby, groupby_obj from .load_python_class import load_python_class from .merge import merge from .replace_or_append_item import replace_or_append_item @@ -20,10 +20,13 @@ from .strip_empties import strip_empties_from_dict, strip_empties_from_list, strip_null_from_data from .template import template from .template_var import template_var +from .undefined import Undefined, UndefinedType from .unique import unique __all__ = [ "AvdStringFormatter", + "Undefined", + "UndefinedType", "append_if_not_duplicate", "batch", "compare_dicts", @@ -37,6 +40,7 @@ "get", "get_v2", "groupby", + "groupby_obj", "load_python_class", "merge", "replace_or_append_item", diff --git a/python-avd/pyavd/_utils/default.py b/python-avd/pyavd/_utils/default.py index 994c52989f3..29acab5c9fd 100644 --- a/python-avd/pyavd/_utils/default.py +++ b/python-avd/pyavd/_utils/default.py @@ -1,26 +1,33 @@ # Copyright (c) 2023-2024 Arista Networks, Inc. # Use of this source code is governed by the Apache License 2.0 # that can be found in the LICENSE file. -from typing import Any +from __future__ import annotations +from typing import TYPE_CHECKING -def default(*values: Any) -> Any: +if TYPE_CHECKING: + from typing import TypeVar + + # TODO: Once we drop 3.10 support this can be imported from typing. + from typing_extensions import Unpack + + T = TypeVar("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. Last resort is to return None. - Parameters - ---------- - *values : any - One or more values to test + Args: + *values: Optional values to test + final_value: Final value to test Returns: - ------- - any First value which is not None """ for value in values: if value is not None: return value - return None + return None # Type hint does not allow this, but it will only happen if all values are None, hence T should include None diff --git a/python-avd/pyavd/_utils/get_all.py b/python-avd/pyavd/_utils/get_all.py index 49fde9e909e..c0d1ba61cc3 100644 --- a/python-avd/pyavd/_utils/get_all.py +++ b/python-avd/pyavd/_utils/get_all.py @@ -65,6 +65,20 @@ def get_all(data: Any, path: str, required: bool = False, org_path: str | None = return [value] + if isinstance(data, object): + value = getattr(data, path_elements[0], None) + + if value is None: + if required: + raise AristaAvdMissingVariableError(org_path) + + return [] + + if len(path_elements) > 1: + return get_all(value, ".".join(path_elements[1:]), required=required, org_path=org_path) + + return [value] + return [] diff --git a/python-avd/pyavd/_utils/groupby.py b/python-avd/pyavd/_utils/groupby.py index e9c2e965eec..7070924c800 100644 --- a/python-avd/pyavd/_utils/groupby.py +++ b/python-avd/pyavd/_utils/groupby.py @@ -3,7 +3,9 @@ # that can be found in the LICENSE file. from collections.abc import Iterator from itertools import groupby as itergroupby -from typing import Any +from typing import Any, TypeVar + +T = TypeVar("T") def groupby(list_of_dictionaries: list, key: str) -> Iterator: @@ -14,3 +16,13 @@ def getkey(dictionary: dict) -> Any: sorted_list = sorted(list_of_dictionaries, key=getkey) return itergroupby(sorted_list, getkey) + + +def groupby_obj(list_of_objects: list[T], attr: str) -> Iterator[tuple[Any, Iterator[T]]]: + """Group list of object by attribute.""" + + def getkey(obj: object) -> Any: + return getattr(obj, attr, None) + + sorted_list = sorted(list_of_objects, key=getkey) + return itergroupby(sorted_list, getkey) diff --git a/python-avd/pyavd/_utils/merge/__init__.py b/python-avd/pyavd/_utils/merge/__init__.py index b49d5fac8ec..490d6c5f08c 100644 --- a/python-avd/pyavd/_utils/merge/__init__.py +++ b/python-avd/pyavd/_utils/merge/__init__.py @@ -46,7 +46,7 @@ def _strategy_must_match(_config: object, path: list, base: Any, nxt: Any) -> An def merge( base: Any, - *nxt_list: list[Any], + *nxt_list: Any, recursive: bool = True, list_merge: str = "append", same_key_strategy: str = "override", diff --git a/python-avd/pyavd/_utils/undefined.py b/python-avd/pyavd/_utils/undefined.py new file mode 100644 index 00000000000..544bdaf6dca --- /dev/null +++ b/python-avd/pyavd/_utils/undefined.py @@ -0,0 +1,21 @@ +# Copyright (c) 2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from typing import Any, Literal + + +class UndefinedType: + """Singleton used instead of None to detect fields that are not set specifically.""" + + _instance: "UndefinedType" + + def __new__(cls, *_args: Any, **_kwargs: Any) -> "UndefinedType": + if not hasattr(cls, "_instance"): + cls._instance = object.__new__(cls) + return cls._instance + + def __bool__(self) -> Literal[False]: + return False + + +Undefined = UndefinedType() diff --git a/python-avd/pyavd/api/interface_descriptions/__init__.py b/python-avd/pyavd/api/interface_descriptions/__init__.py index 4c9ce2aef3d..0b0e082cac0 100644 --- a/python-avd/pyavd/api/interface_descriptions/__init__.py +++ b/python-avd/pyavd/api/interface_descriptions/__init__.py @@ -57,7 +57,7 @@ def underlay_ethernet_interface(self, data: InterfaceDescriptionData) -> str: - wan_carrier - wan_circuit_id. """ - if template_path := self.shared_utils.interface_descriptions_templates.get("underlay_ethernet_interfaces"): + if template_path := self.shared_utils.node_type_key_data.interface_descriptions.underlay_ethernet_interfaces: return self._template( template_path, link={ @@ -70,9 +70,9 @@ def underlay_ethernet_interface(self, data: InterfaceDescriptionData) -> str: if data.description is not None: description = data.description elif data.link_type in ("underlay_p2p", "l3_edge", "core_interfaces"): - description = self.shared_utils.default_underlay_p2p_ethernet_description + description = self.inputs.default_underlay_p2p_ethernet_description elif data.link_type == "underlay_l2": - description = self.shared_utils.underlay_l2_ethernet_description + description = self.inputs.underlay_l2_ethernet_description else: elems = [data.wan_carrier, data.wan_circuit_id, data.peer, data.peer_interface] description = "_".join([elem for elem in elems if elem]) @@ -107,7 +107,7 @@ def underlay_port_channel_interface(self, data: InterfaceDescriptionData) -> str - overlay_routing_protocol - type. """ - if template_path := self.shared_utils.interface_descriptions_templates.get("underlay_port_channel_interfaces"): + if template_path := self.shared_utils.node_type_key_data.interface_descriptions.underlay_port_channel_interfaces: return self._template( template_path, link={ @@ -122,10 +122,10 @@ def underlay_port_channel_interface(self, data: InterfaceDescriptionData) -> str if data.port_channel_description is not None: description = data.port_channel_description elif data.link_type in ("l3_edge", "core_interfaces"): - description = self.shared_utils.default_underlay_p2p_port_channel_description + description = self.inputs.default_underlay_p2p_port_channel_description else: # This is for L2 port-channels - description = self.shared_utils.underlay_l2_port_channel_description + description = self.inputs.underlay_l2_port_channel_description return AvdStringFormatter().format( description, @@ -161,7 +161,7 @@ def mlag_ethernet_interface(self, data: InterfaceDescriptionData) -> str: - overlay_routing_protocol - type. """ - if template_path := self.shared_utils.interface_descriptions_templates.get("mlag_ethernet_interfaces"): + if template_path := self.shared_utils.node_type_key_data.interface_descriptions.mlag_ethernet_interfaces: return self._template( template_path, mlag_interface=data.interface, @@ -169,7 +169,7 @@ def mlag_ethernet_interface(self, data: InterfaceDescriptionData) -> str: ) return AvdStringFormatter().format( - self.shared_utils.mlag_member_description, + self.inputs.mlag_member_description, **strip_null_from_data( { "mlag_peer": data.mlag_peer, @@ -199,7 +199,7 @@ def mlag_port_channel_interface(self, data: InterfaceDescriptionData) -> str: - overlay_routing_protocol - type. """ - if template_path := self.shared_utils.interface_descriptions_templates.get("mlag_port_channel_interfaces"): + if template_path := self.shared_utils.node_type_key_data.interface_descriptions.mlag_port_channel_interfaces: return self._template( template_path, mlag_interfaces=data.mlag_interfaces, @@ -208,7 +208,7 @@ def mlag_port_channel_interface(self, data: InterfaceDescriptionData) -> str: ) return AvdStringFormatter().format( - self.shared_utils.mlag_port_channel_description, + self.inputs.mlag_port_channel_description, **strip_null_from_data( { "mlag_peer": data.mlag_peer, @@ -234,7 +234,7 @@ def mlag_peer_svi(self, data: InterfaceDescriptionData) -> str: - type. """ return AvdStringFormatter().format( - self.shared_utils.mlag_peer_svi_description, + self.inputs.mlag_peer_svi_description, **strip_null_from_data( { "mlag_peer": data.mlag_peer, @@ -258,7 +258,7 @@ def mlag_peer_l3_svi(self, data: InterfaceDescriptionData) -> str: - type. """ return AvdStringFormatter().format( - self.shared_utils.mlag_peer_l3_svi_description, + self.inputs.mlag_peer_l3_svi_description, **strip_null_from_data( { "mlag_peer": data.mlag_peer, @@ -283,7 +283,7 @@ def mlag_peer_l3_vrf_svi(self, data: InterfaceDescriptionData) -> str: - type. """ return AvdStringFormatter().format( - self.shared_utils.mlag_peer_l3_vrf_svi_description, + self.inputs.mlag_peer_l3_vrf_svi_description, **strip_null_from_data( { "mlag_peer": data.mlag_peer, @@ -312,7 +312,7 @@ def connected_endpoints_ethernet_interface(self, data: InterfaceDescriptionData) - overlay_routing_protocol - type. """ - if template_path := self.shared_utils.interface_descriptions_templates.get("connected_endpoints_ethernet_interfaces"): + if template_path := self.shared_utils.node_type_key_data.interface_descriptions.connected_endpoints_ethernet_interfaces: return self._template( template_path, peer=data.peer, @@ -324,9 +324,9 @@ def connected_endpoints_ethernet_interface(self, data: InterfaceDescriptionData) if data.description: description = data.description elif data.peer_type == "network_port": - description = self.shared_utils.default_network_ports_description + description = self.inputs.default_network_ports_description else: - description = self.shared_utils.default_connected_endpoints_description + description = self.inputs.default_connected_endpoints_description return AvdStringFormatter().format( description, @@ -360,7 +360,7 @@ def connected_endpoints_port_channel_interface(self, data: InterfaceDescriptionD - overlay_routing_protocol - type. """ - if template_path := self.shared_utils.interface_descriptions_templates.get("connected_endpoints_port_channel_interfaces"): + if template_path := self.shared_utils.node_type_key_data.interface_descriptions.connected_endpoints_port_channel_interfaces: return self._template( template_path, peer=data.peer, @@ -372,9 +372,9 @@ def connected_endpoints_port_channel_interface(self, data: InterfaceDescriptionD if data.port_channel_description: port_channel_description = data.port_channel_description elif data.peer_type == "network_port": - port_channel_description = self.shared_utils.default_network_ports_port_channel_description + port_channel_description = self.inputs.default_network_ports_port_channel_description else: - port_channel_description = self.shared_utils.default_connected_endpoints_port_channel_description + port_channel_description = self.inputs.default_connected_endpoints_port_channel_description # Template the adapter description in case it is being referenced in the port_channel_description adapter_description = ( @@ -418,8 +418,8 @@ def router_id_loopback_interface(self, data: InterfaceDescriptionData) -> str: - type. """ if template_path := default( - self.shared_utils.interface_descriptions_templates.get("router_id_loopback_interface"), - self.shared_utils.interface_descriptions_templates.get("overlay_loopback_interface"), + self.shared_utils.node_type_key_data.interface_descriptions.router_id_loopback_interface, + self.shared_utils.node_type_key_data.interface_descriptions.overlay_loopback_interface, ): return self._template(template_path, overlay_loopback_description=data.description, router_id_loopback_description=data.description) @@ -436,7 +436,7 @@ def vtep_loopback_interface(self, data: InterfaceDescriptionData) -> str: - overlay_routing_protocol - type """ - if template_path := self.shared_utils.interface_descriptions_templates.get("vtep_loopback_interface"): + if template_path := self.shared_utils.node_type_key_data.interface_descriptions.vtep_loopback_interface: return self._template(template_path, vtep_loopback_description=data.description) return data.description @@ -575,7 +575,7 @@ def mlag_peer_port_channel_id(self) -> int: @property def mlag_peer_vlan(self) -> int: - return self._shared_utils.mlag_peer_vlan + return self._shared_utils.node_config.mlag_peer_vlan @property def mlag_peer_l3_vlan(self) -> int | None: diff --git a/python-avd/pyavd/api/ip_addressing/__init__.py b/python-avd/pyavd/api/ip_addressing/__init__.py index 3f6ff6047ca..e300458354b 100644 --- a/python-avd/pyavd/api/ip_addressing/__init__.py +++ b/python-avd/pyavd/api/ip_addressing/__init__.py @@ -40,12 +40,14 @@ def _mlag_ip(self, pool: str, ip_offset: int, address_family: str = "ipv4") -> s - same_subnet: offset from pool is always 0. All MLAG pairs will be using the same subnet (default /31). Requires the pool to have the same prefix length. """ - prefixlen = self._fabric_ip_addressing_mlag_ipv6_prefix_length if address_family == "ipv6" else self._fabric_ip_addressing_mlag_ipv4_prefix_length - if self._fabric_ipaddress_mlag_algorithm == "odd_id": + prefixlen = ( + self.inputs.fabric_ip_addressing.mlag.ipv6_prefix_length if address_family == "ipv6" else self.inputs.fabric_ip_addressing.mlag.ipv4_prefix_length + ) + if self.inputs.fabric_ip_addressing.mlag.algorithm == "odd_id": offset = self._mlag_odd_id_based_offset return get_ip_from_pool(pool, prefixlen, offset, ip_offset) - if self._fabric_ipaddress_mlag_algorithm == "same_subnet": + if self.inputs.fabric_ip_addressing.mlag.algorithm == "same_subnet": pool_network = ipaddress.ip_network(pool, strict=False) if pool_network.prefixlen != prefixlen: msg = f"MLAG same_subnet addressing requires the pool to be a /{prefixlen}" @@ -58,7 +60,7 @@ def _mlag_ip(self, pool: str, ip_offset: int, address_family: str = "ipv4") -> s def mlag_ibgp_peering_ip_primary(self, mlag_ibgp_peering_ipv4_pool: str) -> str: """Return IP for L3 Peerings in VRFs for MLAG Primary.""" - if template_path := self.shared_utils.ip_addressing_templates.get("mlag_ibgp_peering_ip_primary"): + if template_path := self.shared_utils.node_type_key_data.ip_addressing.mlag_ibgp_peering_ip_primary: return self._template( template_path, vrf={"mlag_ibgp_peering_ipv4_pool": mlag_ibgp_peering_ipv4_pool}, @@ -68,7 +70,7 @@ def mlag_ibgp_peering_ip_primary(self, mlag_ibgp_peering_ipv4_pool: str) -> str: def mlag_ibgp_peering_ip_secondary(self, mlag_ibgp_peering_ipv4_pool: str) -> str: """Return IP for L3 Peerings in VRFs for MLAG Secondary.""" - if template_path := self.shared_utils.ip_addressing_templates.get("mlag_ibgp_peering_ip_secondary"): + if template_path := self.shared_utils.node_type_key_data.ip_addressing.mlag_ibgp_peering_ip_secondary: return self._template( template_path, vrf={"mlag_ibgp_peering_ipv4_pool": mlag_ibgp_peering_ipv4_pool}, @@ -82,8 +84,8 @@ def mlag_ip_primary(self) -> str: Default pool is "mlag_peer_ipv4_pool" """ - if self.shared_utils.mlag_peer_address_family == "ipv6": - if template_path := self.shared_utils.ip_addressing_templates.get("mlag_ip_primary"): + if self.shared_utils.node_config.mlag_peer_address_family == "ipv6": + if template_path := self.shared_utils.node_type_key_data.ip_addressing.mlag_ip_primary: return self._template( template_path, mlag_primary_id=self._mlag_primary_id, @@ -91,9 +93,9 @@ def mlag_ip_primary(self) -> str: switch_data={"combined": {"mlag_peer_ipv6_pool": self._mlag_peer_ipv6_pool}}, ) - return self._mlag_ip(self._mlag_peer_ipv6_pool, 0, self.shared_utils.mlag_peer_address_family) + return self._mlag_ip(self._mlag_peer_ipv6_pool, 0, self.shared_utils.node_config.mlag_peer_address_family) - if template_path := self.shared_utils.ip_addressing_templates.get("mlag_ip_primary"): + if template_path := self.shared_utils.node_type_key_data.ip_addressing.mlag_ip_primary: return self._template( template_path, mlag_primary_id=self._mlag_primary_id, @@ -109,8 +111,8 @@ def mlag_ip_secondary(self) -> str: Default pool is "mlag_peer_ipv4_pool" """ - if self.shared_utils.mlag_peer_address_family == "ipv6": - if template_path := self.shared_utils.ip_addressing_templates.get("mlag_ip_secondary"): + if self.shared_utils.node_config.mlag_peer_address_family == "ipv6": + if template_path := self.shared_utils.node_type_key_data.ip_addressing.mlag_ip_secondary: return self._template( template_path, mlag_primary_id=self._mlag_primary_id, @@ -118,9 +120,9 @@ def mlag_ip_secondary(self) -> str: switch_data={"combined": {"mlag_peer_ipv6_pool": self._mlag_peer_ipv6_pool}}, ) - return self._mlag_ip(self._mlag_peer_ipv6_pool, 1, self.shared_utils.mlag_peer_address_family) + return self._mlag_ip(self._mlag_peer_ipv6_pool, 1, self.shared_utils.node_config.mlag_peer_address_family) - if template_path := self.shared_utils.ip_addressing_templates.get("mlag_ip_secondary"): + if template_path := self.shared_utils.node_type_key_data.ip_addressing.mlag_ip_secondary: return self._template( template_path, mlag_primary_id=self._mlag_primary_id, @@ -136,7 +138,7 @@ def mlag_l3_ip_primary(self) -> str: Default pool is "mlag_peer_l3_ipv4_pool" """ - if template_path := self.shared_utils.ip_addressing_templates.get("mlag_l3_ip_primary"): + if template_path := self.shared_utils.node_type_key_data.ip_addressing.mlag_l3_ip_primary: return self._template( template_path, mlag_primary_id=self._mlag_primary_id, @@ -152,7 +154,7 @@ def mlag_l3_ip_secondary(self) -> str: Default pool is "mlag_peer_l3_ipv4_pool" """ - if template_path := self.shared_utils.ip_addressing_templates.get("mlag_l3_ip_secondary"): + if template_path := self.shared_utils.node_type_key_data.ip_addressing.mlag_l3_ip_secondary: return self._template( template_path, mlag_primary_id=self._mlag_primary_id, @@ -165,13 +167,13 @@ def mlag_l3_ip_secondary(self) -> str: def p2p_uplinks_ip(self, uplink_switch_index: int) -> str: """Return Child IP for P2P Uplinks.""" uplink_switch_index = int(uplink_switch_index) - if template_path := self.shared_utils.ip_addressing_templates.get("p2p_uplinks_ip"): + if template_path := self.shared_utils.node_type_key_data.ip_addressing.p2p_uplinks_ip: return self._template( template_path, uplink_switch_index=uplink_switch_index, ) - prefixlen = self._fabric_ip_addressing_p2p_uplinks_ipv4_prefix_length + prefixlen = self.inputs.fabric_ip_addressing.p2p_uplinks.ipv4_prefix_length p2p_ipv4_pool, offset = self._get_p2p_ipv4_pool_and_offset(uplink_switch_index) return get_ip_from_pool(p2p_ipv4_pool, prefixlen, offset, 1) @@ -179,13 +181,13 @@ def p2p_uplinks_ip(self, uplink_switch_index: int) -> str: def p2p_uplinks_peer_ip(self, uplink_switch_index: int) -> str: """Return Parent IP for P2P Uplinks.""" uplink_switch_index = int(uplink_switch_index) - if template_path := self.shared_utils.ip_addressing_templates.get("p2p_uplinks_peer_ip"): + if template_path := self.shared_utils.node_type_key_data.ip_addressing.p2p_uplinks_peer_ip: return self._template( template_path, uplink_switch_index=uplink_switch_index, ) - prefixlen = self._fabric_ip_addressing_p2p_uplinks_ipv4_prefix_length + prefixlen = self.inputs.fabric_ip_addressing.p2p_uplinks.ipv4_prefix_length p2p_ipv4_pool, offset = self._get_p2p_ipv4_pool_and_offset(uplink_switch_index) return get_ip_from_pool(p2p_ipv4_pool, prefixlen, offset, 0) @@ -225,7 +227,7 @@ def router_id(self) -> str: if self._loopback_ipv4_address: return self._loopback_ipv4_address - if template_path := self.shared_utils.ip_addressing_templates.get("router_id"): + if template_path := self.shared_utils.node_type_key_data.ip_addressing.router_id: return self._template( template_path, switch_id=self._id, @@ -243,14 +245,6 @@ def ipv6_router_id(self) -> str: Default pool is "loopback_ipv6_pool" Default offset from pool is `id + loopback_ipv6_offset` """ - if template_path := self.shared_utils.ip_addressing_templates.get("ipv6_router_id"): - return self._template( - template_path, - switch_id=self._id, - loopback_ipv6_pool=self._loopback_ipv6_pool, - loopback_ipv6_offset=self._loopback_ipv6_offset, - ) - offset = self._id + self._loopback_ipv6_offset return get_ip_from_pool(self._loopback_ipv6_pool, 128, offset, 0) @@ -265,7 +259,7 @@ def vtep_ip_mlag(self) -> str: if self._vtep_loopback_ipv4_address: return self._vtep_loopback_ipv4_address - if template_path := self.shared_utils.ip_addressing_templates.get("vtep_ip_mlag"): + if template_path := self.shared_utils.node_type_key_data.ip_addressing.vtep_ip_mlag: return self._template( template_path, switch_id=self._id, @@ -289,7 +283,7 @@ def vtep_ip(self) -> str: if self._vtep_loopback_ipv4_address: return self._vtep_loopback_ipv4_address - if template_path := self.shared_utils.ip_addressing_templates.get("vtep_ip"): + if template_path := self.shared_utils.node_type_key_data.ip_addressing.vtep_ip: return self._template( template_path, switch_id=self._id, @@ -308,7 +302,7 @@ def vrf_loopback_ip(self, pool: str) -> str: Used for "vtep_diagnostic.loopback". """ - offset = self.shared_utils.id + self.shared_utils.loopback_ipv4_offset + offset = self.shared_utils.id + self.shared_utils.node_config.loopback_ipv4_offset return get_ip_from_pool(pool, 32, offset, 0) def vrf_loopback_ipv6(self, pool: str) -> str: @@ -319,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( @@ -346,7 +340,7 @@ def evpn_underlay_l2_multicast_group( def wan_ha_ip(self) -> str: """Return the WAN HA local IP address.""" wan_ha_ipv4_pool = self.shared_utils.wan_ha_ipv4_pool - prefixlen = self.shared_utils.fabric_ip_addressing_wan_ha_ipv4_prefix_length + prefixlen = self.inputs.fabric_ip_addressing.wan_ha.ipv4_prefix_length if self.shared_utils.is_first_ha_peer: ip_address = get_ip_from_pool(wan_ha_ipv4_pool, prefixlen, 0, 0) @@ -358,7 +352,7 @@ def wan_ha_ip(self) -> str: def wan_ha_peer_ip(self) -> str: """Return the WAN HA peer IP.""" wan_ha_ipv4_pool = self.shared_utils.wan_ha_ipv4_pool - prefixlen = self.shared_utils.fabric_ip_addressing_wan_ha_ipv4_prefix_length + prefixlen = self.inputs.fabric_ip_addressing.wan_ha.ipv4_prefix_length if self.shared_utils.is_first_ha_peer: ip_address = get_ip_from_pool(wan_ha_ipv4_pool, prefixlen, 0, 1) diff --git a/python-avd/pyavd/api/ip_addressing/utils.py b/python-avd/pyavd/api/ip_addressing/utils.py index ca6191fd470..72640debc6b 100644 --- a/python-avd/pyavd/api/ip_addressing/utils.py +++ b/python-avd/pyavd/api/ip_addressing/utils.py @@ -35,22 +35,6 @@ def _mlag_secondary_id(self: AvdIpAddressing) -> int: raise AristaAvdInvalidInputsError(msg) return self.shared_utils.mlag_switch_ids["secondary"] - @cached_property - def _fabric_ipaddress_mlag_algorithm(self: AvdIpAddressing) -> str: - return self.shared_utils.fabric_ip_addressing_mlag_algorithm - - @cached_property - def _fabric_ip_addressing_mlag_ipv4_prefix_length(self: AvdIpAddressing) -> int: - return self.shared_utils.fabric_ip_addressing_mlag_ipv4_prefix_length - - @cached_property - def _fabric_ip_addressing_mlag_ipv6_prefix_length(self: AvdIpAddressing) -> int: - return self.shared_utils.fabric_ip_addressing_mlag_ipv6_prefix_length - - @cached_property - def _fabric_ip_addressing_p2p_uplinks_ipv4_prefix_length(self: AvdIpAddressing) -> int: - return self.shared_utils.fabric_ip_addressing_p2p_uplinks_ipv4_prefix_length - @cached_property def _mlag_peer_ipv4_pool(self: AvdIpAddressing) -> str: return self.shared_utils.mlag_peer_ipv4_pool @@ -65,10 +49,10 @@ def _mlag_peer_l3_ipv4_pool(self: AvdIpAddressing) -> str: @cached_property def _uplink_ipv4_pool(self: AvdIpAddressing) -> str: - if self.shared_utils.uplink_ipv4_pool is None: + if self.shared_utils.node_config.uplink_ipv4_pool is None: msg = "'uplink_ipv4_pool' is required to calculate uplink IP addresses." raise AristaAvdInvalidInputsError(msg) - return self.shared_utils.uplink_ipv4_pool + return self.shared_utils.node_config.uplink_ipv4_pool @cached_property def _id(self: AvdIpAddressing) -> int: @@ -83,11 +67,11 @@ 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: - return self.shared_utils.loopback_ipv4_address + def _loopback_ipv4_address(self: AvdIpAddressing) -> str | None: + return self.shared_utils.node_config.loopback_ipv4_address @cached_property def _loopback_ipv4_pool(self: AvdIpAddressing) -> str: @@ -95,7 +79,7 @@ def _loopback_ipv4_pool(self: AvdIpAddressing) -> str: @cached_property def _loopback_ipv4_offset(self: AvdIpAddressing) -> int: - return self.shared_utils.loopback_ipv4_offset + return self.shared_utils.node_config.loopback_ipv4_offset @cached_property def _loopback_ipv6_pool(self: AvdIpAddressing) -> str: @@ -103,11 +87,11 @@ def _loopback_ipv6_pool(self: AvdIpAddressing) -> str: @cached_property def _loopback_ipv6_offset(self: AvdIpAddressing) -> int: - return self.shared_utils.loopback_ipv6_offset + return self.shared_utils.node_config.loopback_ipv6_offset @cached_property - def _vtep_loopback_ipv4_address(self: AvdIpAddressing) -> str: - return self.shared_utils.vtep_loopback_ipv4_address + def _vtep_loopback_ipv4_address(self: AvdIpAddressing) -> str | None: + return self.shared_utils.node_config.vtep_loopback_ipv4_address @cached_property def _vtep_loopback_ipv4_pool(self: AvdIpAddressing) -> str: @@ -158,9 +142,7 @@ def _get_downlink_ipv4_pool_and_offset(self: AvdIpAddressing, uplink_switch_inde f"'downlink_pools' was defined at uplink_switch, but one of the 'uplink_switch_interfaces' ({uplink_switch_interface}) " "in the downlink_switch does not match any of the downlink_pools" ) - raise AristaAvdError( - msg, - ) + raise AristaAvdError(msg) def _get_p2p_ipv4_pool_and_offset(self: AvdIpAddressing, uplink_switch_index: int) -> tuple[str, int]: """ @@ -172,7 +154,7 @@ def _get_p2p_ipv4_pool_and_offset(self: AvdIpAddressing, uplink_switch_index: in One and only one of these pools are required to be set, otherwise an error will be thrown """ - uplink_pool = self.shared_utils.uplink_ipv4_pool + uplink_pool = self.shared_utils.node_config.uplink_ipv4_pool if uplink_pool is not None: uplink_offset = ((self._id - 1) * self._max_uplink_switches * self._max_parallel_uplinks) + uplink_switch_index diff --git a/python-avd/pyavd/get_avd_facts.py b/python-avd/pyavd/get_avd_facts.py index 09ce29e94cc..53edd9d8b4b 100644 --- a/python-avd/pyavd/get_avd_facts.py +++ b/python-avd/pyavd/get_avd_facts.py @@ -67,6 +67,7 @@ def _create_avd_switch_facts_instances(all_inputs: dict[str, dict]) -> dict: """ # pylint: disable=import-outside-toplevel from ._eos_designs.eos_designs_facts import EosDesignsFacts + from ._eos_designs.schema import EosDesigns from ._eos_designs.shared_utils import SharedUtils from .avd_schema_tools import EosDesignsAvdSchemaTools @@ -81,11 +82,14 @@ def _create_avd_switch_facts_instances(all_inputs: dict[str, dict]) -> dict: hostvars, ) + # Load input vars into the EosDesigns data class. + inputs = EosDesigns._from_dict(hostvars) + # Initialize SharedUtils class to be passed to each python_module below. - shared_utils = SharedUtils(hostvars=mapped_hostvars, templar=None, schema=EosDesignsAvdSchemaTools().avdschema) + shared_utils = SharedUtils(hostvars=mapped_hostvars, inputs=inputs, templar=None, schema=EosDesignsAvdSchemaTools().avdschema) # Notice templar is set as None, so any calls to jinja templates will fail with Nonetype has no "_loader" attribute - avd_switch_facts[hostname] = {"switch": EosDesignsFacts(hostvars=mapped_hostvars, shared_utils=shared_utils)} + avd_switch_facts[hostname] = {"switch": EosDesignsFacts(hostvars=mapped_hostvars, inputs=inputs, shared_utils=shared_utils)} return avd_switch_facts diff --git a/python-avd/pyavd/j2filters/natural_sort.py b/python-avd/pyavd/j2filters/natural_sort.py index 5c167c8e451..698cbcab5c1 100644 --- a/python-avd/pyavd/j2filters/natural_sort.py +++ b/python-avd/pyavd/j2filters/natural_sort.py @@ -4,6 +4,7 @@ from __future__ import annotations import re +from collections.abc import Iterable, Mapping from typing import Any from jinja2.runtime import Undefined @@ -30,22 +31,19 @@ def convert(text: str, ignore_case: bool) -> int | str: return text.lower() if ignore_case else text -def natural_sort(iterable: list | dict | str | None, sort_key: str | None = None, *, strict: bool = True, ignore_case: bool = True) -> list: +def natural_sort(iterable: Iterable | None, sort_key: str | None = None, *, strict: bool = True, ignore_case: bool = True) -> list: """Sorts an iterable in a natural (alphanumeric) order. Args: - ----- - iterable (list | dict | str | None): Input iterable. - sort_key (str | None, optional): Key to sort by, defaults to None. - strict (bool, optional): If strict is True, raise an error is the sort_key is missing. - ignore_case (bool, optional): If ignore_case is True, strings are applied lower() function. + iterable: Input iterable. + sort_key: Key to sort by, defaults to None. + strict: If strict is True, raise an error is the sort_key is missing. + ignore_case: If ignore_case is True, strings are applied lower() function. Returns: - ------- list: Sorted iterable. Raises: - ------ KeyError, AttributeError: if strict=True and sort_key is not present in an item in the iterable. """ if isinstance(iterable, Undefined) or iterable is None: @@ -53,7 +51,7 @@ def natural_sort(iterable: list | dict | str | None, sort_key: str | None = None def alphanum_key(key: Any) -> list: pattern = r"(\d+)" - if sort_key is not None and isinstance(key, dict): + if sort_key is not None and isinstance(key, Mapping): if strict and sort_key not in key: msg = f"Missing key '{sort_key}' in item to sort {key}." raise KeyError(msg) @@ -62,7 +60,7 @@ def alphanum_key(key: Any) -> list: if strict and not hasattr(key, sort_key): msg = f"Missing attribute '{sort_key}' in item to sort {key}." raise AttributeError(msg) - return [convert(c, ignore_case) for c in re.split(pattern, getattr(key, sort_key))] + return [convert(c, ignore_case) for c in re.split(pattern, str(getattr(key, sort_key)))] return [convert(c, ignore_case) for c in re.split(pattern, str(key))] return sorted(iterable, key=alphanum_key) diff --git a/python-avd/pyavd/j2filters/range_expand.py b/python-avd/pyavd/j2filters/range_expand.py index 303625beed0..600c59cbcc3 100644 --- a/python-avd/pyavd/j2filters/range_expand.py +++ b/python-avd/pyavd/j2filters/range_expand.py @@ -5,8 +5,8 @@ from __future__ import annotations import re +from collections.abc import Sequence from dataclasses import dataclass -from typing import Any @dataclass @@ -82,15 +82,15 @@ def expand_module(interface_string: str, data: InterfaceData) -> list: return result -def range_expand(range_to_expand: Any) -> list: - if not isinstance(range_to_expand, (list, str)): - msg = f"value must be of type list or str, got {type(range_to_expand)}" +def range_expand(range_to_expand: Sequence) -> list: + if not isinstance(range_to_expand, Sequence): + msg = f"value must be a Sequence, got {type(range_to_expand)}" raise TypeError(msg) result = [] # If we got a list, unpack it and run this function recursively - if isinstance(range_to_expand, list): + if not isinstance(range_to_expand, str): for r in range_to_expand: result.extend(range_expand(r)) diff --git a/python-avd/pyavd/templater.py b/python-avd/pyavd/templater.py index 8d98e413127..0a9e8712a09 100644 --- a/python-avd/pyavd/templater.py +++ b/python-avd/pyavd/templater.py @@ -45,7 +45,7 @@ def __contains__(self, _item: int) -> Undefined: class Templar: - def __init__(self, precompiled_templates_path: str, searchpaths: list[str] | None = None) -> None: + def __init__(self, precompiled_templates_path: str | Path, searchpaths: list[str | Path] | None = None) -> None: if not RUNNING_FROM_SRC: self.loader = ModuleLoader(precompiled_templates_path) else: @@ -115,7 +115,7 @@ def import_filters_and_tests(self) -> None: def render_template_from_file(self, template_file: str, template_vars: dict) -> str: return self.environment.get_template(template_file).render(template_vars) - def compile_templates_in_paths(self, precompiled_templates_path: str, searchpaths: list[str]) -> None: + def compile_templates_in_paths(self, precompiled_templates_path: str | Path, searchpaths: list[str | Path]) -> None: """ Compile the Jinja2 templates in the path. diff --git a/python-avd/pyproject.toml b/python-avd/pyproject.toml index 4c7397b0a0c..afe998a215e 100644 --- a/python-avd/pyproject.toml +++ b/python-avd/pyproject.toml @@ -72,6 +72,7 @@ requires = [ "pydantic>=2.3.0", "cryptography>=38.0.4", "aristaproto>=0.1.1", + "ruff==0.7.2", ] build-backend = "custom_build_backend" backend-path = ["scripts"] diff --git a/python-avd/schema_tools/build_schemas.py b/python-avd/schema_tools/build_schemas.py index cbe25e46580..49738c26aaa 100644 --- a/python-avd/schema_tools/build_schemas.py +++ b/python-avd/schema_tools/build_schemas.py @@ -2,6 +2,7 @@ # Use of this source code is governed by the Apache License 2.0 # that can be found in the LICENSE file. import logging +import subprocess from pathlib import Path from textwrap import indent @@ -10,7 +11,9 @@ from yaml import dump as yaml_dump from yaml import load as yaml_load -from .constants import DOCS_PATHS, LICENSE_HEADER, SCHEMA_FRAGMENTS_PATHS, SCHEMA_PATHS +from .constants import DOCS_PATHS, LICENSE_HEADER, PYTHON_CLASS_PATHS, SCHEMA_FRAGMENTS_PATHS, SCHEMA_PATHS +from .generate_classes.src_generators import FileSrc +from .generate_classes.utils import generate_class_name from .generate_docs.mdtabsgen import get_md_tabs from .metaschema.meta_schema_model import AristaAvdSchema from .store import create_store @@ -66,6 +69,7 @@ def validate_schemas(schema_store: dict) -> None: def build_schema_tables(schema_store: dict) -> None: """Build schema tables.""" + LOGGER.info("Rebuilding schema documentation tables...") for schema_name in SCHEMA_PATHS: if schema_name not in SCHEMA_FRAGMENTS_PATHS: continue @@ -86,11 +90,33 @@ def build_schema_tables(schema_store: dict) -> None: file.unlink() +def build_schema_classes() -> None: + """Build Python Classes from schema.""" + LOGGER.info("Rebuilding schema Python Classes...") + # We use a special schema store since we only wish to resolve a subset of the $defs. This is to have more reuse of the generated classes + raw_yaml_schema_store = create_store(load_from_yaml=True) + for schema_name, python_class_path in PYTHON_CLASS_PATHS.items(): + if schema_name not in raw_yaml_schema_store: + msg = f"Invalid schema name '{schema_name}'" + raise KeyError(msg) + + schema = AristaAvdSchema(_resolve_schema=schema_name, **raw_yaml_schema_store[schema_name]) + LOGGER.info("Building Python Classes from schema: %s", schema_name) + schemasrc = schema._generate_class_src(class_name=generate_class_name(schema_name)) + src_file_contents = FileSrc(classes=[schemasrc.cls]) + with python_class_path.open(mode="w", encoding="UTF-8") as file: + file.write(str(src_file_contents)) + + LOGGER.info("Running 'ruff' for Python class file: %s", python_class_path) + subprocess.run(["ruff", "check", "--fix", str(python_class_path)], check=False) # noqa: S603, S607 + subprocess.run(["ruff", "format", str(python_class_path)], check=False) # noqa: S603, S607 + + def build_schemas() -> None: """Combines the schema fragments, and rebuild the pickled schemas.""" combine_schemas() LOGGER.info("Rebuilding pickled schemas") schema_store = create_store(force_rebuild=True) validate_schemas(schema_store) - LOGGER.info("Rebuilding schemas documentation tables...") build_schema_tables(schema_store) + build_schema_classes() diff --git a/python-avd/schema_tools/constants.py b/python-avd/schema_tools/constants.py index aaf8bf7b72e..1e6e9088d1e 100644 --- a/python-avd/schema_tools/constants.py +++ b/python-avd/schema_tools/constants.py @@ -38,6 +38,10 @@ "eos_cli_config_gen": EOS_CLI_CONFIG_GEN_PICKLED_SCHEMA_PATH, "eos_designs": EOS_DESIGNS_PICKLED_SCHEMA_PATH, } +PYTHON_CLASS_PATHS = { + "eos_cli_config_gen": EOS_CLI_CONFIG_GEN_SCHEMA_DIR.joinpath("__init__.py"), + "eos_designs": EOS_DESIGNS_SCHEMA_DIR.joinpath("__init__.py"), +} DOCS_PATHS = { "eos_cli_config_gen": EOS_CLI_CONFIG_GEN_DOCS_PATH, "eos_designs": EOS_DESIGNS_DOCS_PATH, diff --git a/python-avd/schema_tools/generate_classes/__init__.py b/python-avd/schema_tools/generate_classes/__init__.py new file mode 100644 index 00000000000..e772bee41fe --- /dev/null +++ b/python-avd/schema_tools/generate_classes/__init__.py @@ -0,0 +1,3 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. diff --git a/python-avd/schema_tools/generate_classes/class_src_gen.py b/python-avd/schema_tools/generate_classes/class_src_gen.py new file mode 100644 index 00000000000..bbb16cbc8ea --- /dev/null +++ b/python-avd/schema_tools/generate_classes/class_src_gen.py @@ -0,0 +1,510 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from __future__ import annotations + +from keyword import iskeyword +from typing import TYPE_CHECKING + +from .src_generators import ClassVarSrc, FieldSrc, FieldTypeHintSrc, ListSrc, ModelSrc, SrcData +from .utils import generate_class_name, generate_class_name_from_ref + +if TYPE_CHECKING: + from schema_tools.metaschema.meta_schema_model import AvdSchemaBool, AvdSchemaDict, AvdSchemaField, AvdSchemaInt, AvdSchemaList, AvdSchemaStr + + +class SrcGenBase: + """Provides the method "generate_class_src" used to build source code for Python classes representing the schema.""" + + # TODO: add deprecation handling + # dynamic_valid_values + # Create a base model for lists so child items can be rendered by their own generators instead of trying to handle it inside lists. + + def generate_class_src(self, schema: AvdSchemaField, class_name: str | None = None) -> SrcData: + """ + Returns SrcData for the given schema. + + Recursively walks child schemas and creates nested classes and fields. + """ + self.schema = schema + self.class_name = class_name + + if schema.deprecation and schema.deprecation.removed: + return SrcData() + + return SrcData(field=self.get_field(), cls=self.get_class()) + + def get_field(self) -> FieldSrc | None: + """Returns FieldSrc for the given schema to be used for the field definition in the parent object.""" + if not self.schema._key: + return None + + return FieldSrc( + name=self.get_field_name(), + key=self.get_key(), + field_type=self.get_type(), + type_hints=self.get_type_hints(), + optional=not (bool(self.schema.required) or self.schema._is_primary_key), + default_value=self.get_default(), + description=self.get_description(), + ) + + def get_type(self) -> str: + return self.schema.type + + def get_description(self) -> str | None: + return self.schema.description + + def get_type_hints(self) -> list[FieldTypeHintSrc]: + """Returns a list of FieldTypeHintSrc representing the type hints for this schema.""" + field_type = cls.name if (cls := self.get_class()) else self.schema.type + + return [ + FieldTypeHintSrc( + field_type=field_type, + # TODO: For annotation based validation we need this: annotations=get_annotations_for_field(self.schema), + ) + ] + + def get_class_name(self) -> str: + """Returns the class name to be used for the class definition in the parent object.""" + if self.class_name: + return self.class_name + + return generate_class_name(self.get_key()) + + def get_class(self) -> ModelSrc | None: + """Returns ModelSrc for the given schema to be used for the class definition in the parent object.""" + return None + + def get_key(self) -> str: + """Returns the key name after stripping dynamic key syntax.""" + return self.schema._key.replace("<", "").replace(">", "").replace(".", "_") + + def get_field_name(self) -> str: + """ + Returns the name to be used for the field definition in the parent object. + + Python reserved keywords pr mixed case keys will get a prefix of "field_". + """ + if not self.valid_key: + return f"field_{self.get_key()}" + return self.get_key() + + @property + def valid_key(self) -> bool: + """Check if the key name can be used as field name.""" + return not iskeyword(self.schema._key) and self.schema._key.islower() + + def get_default(self) -> str | None: + """Returns the default value from the schema as a source code string.""" + if self.schema.default is not None: + return str(self.schema.default) + return None + + +class SrcGenInt(SrcGenBase): + """Provides the method "generate_class_src" used to build source code for Python classes representing the schema.""" + + schema: AvdSchemaInt + + def get_type_hints(self) -> list[FieldTypeHintSrc]: + """Returns a list of FieldTypeHintSrc representing the type hints for this schema.""" + field_type = cls.name if (cls := self.get_class()) else self.schema.type + + if self.schema.valid_values is None: + return [FieldTypeHintSrc(field_type=field_type)] + + return [FieldTypeHintSrc(field_type=f"Literal[{', '.join(map(str, self.schema.valid_values))}]")] + + +class SrcGenBool(SrcGenBase): + """Provides the method "generate_class_src" used to build source code for Python classes representing the schema.""" + + schema: AvdSchemaBool + + +class SrcGenStr(SrcGenBase): + """Provides the method "generate_class_src" used to build source code for Python classes representing the schema.""" + + schema: AvdSchemaStr + + def get_default(self) -> str | None: + """Returns the default value from the schema as a source code string.""" + if self.schema.default is not None: + return f'"{self.schema.default}"' + return None + + def get_type_hints(self) -> list[FieldTypeHintSrc]: + """Returns a list of FieldTypeHintSrc representing the type hints for this schema.""" + field_type = cls.name if (cls := self.get_class()) else self.schema.type + + if self.schema.valid_values is None: + return [FieldTypeHintSrc(field_type=field_type)] + + def quote(string: str) -> str: + return f'"{string}"' + + return [FieldTypeHintSrc(field_type=f"Literal[{', '.join(map(quote, self.schema.valid_values))}]")] + + +class SrcGenList(SrcGenBase): + """Provides the method "generate_class_src" used to build source code for Python classes representing the schema.""" + + schema: AvdSchemaList + + def get_type(self) -> str: + return self.get_class_name() + + def generate_class_src(self, schema: AvdSchemaList, class_name: str | None = None) -> SrcData: + """ + Returns SrcData for the given schema. + + Recursively walks child schemas and creates nested classes and fields. + """ + self.schema = schema + self.class_name = class_name + + if schema.deprecation and schema.deprecation.removed: + return SrcData(field=None, cls=None) + + return SrcData(field=self.get_field(), cls=self.get_class(), item_classes=self.get_item_classes()) + + def get_class(self) -> ListSrc: + """Returns ListSrc for the given schema to be used for the class definition in the parent object.""" + if self.schema.field_ref: + # TODO: Currently we only skip resolving ref for indexedlists. Improve this. + return ListSrc( + name=self.get_class_name(), + base_class=generate_class_name_from_ref(self.schema.field_ref), + ) + + class_name = self.get_class_name() + if self.schema.items is None: + item_class_name = "Any" + elif self.schema.items.type in ["dict", "list"]: + item_class_name = f"{class_name}Item" + else: + item_class_name = self.schema.items.type + + # Regular list + if not self.schema.primary_key or self.schema.allow_duplicate_primary_key: + return ListSrc( + name=class_name, + base_class=f"AvdList[{item_class_name}]", + item_type=item_class_name, + description=f"Subclass of AvdList with `{item_class_name}` items.", + ) + + # Indexed list (list with unique primary_key) + if not self.schema.items or self.schema.items.type != "dict" or not self.schema.items.keys: + # This should never happen but helps type system detect the relevant schema type below. + msg = "Some inconsistent types or schema..." + raise TypeError(msg) + + primary_key_type = self.schema.items.keys[self.schema.primary_key].type + return ListSrc( + name=class_name, + base_class=f"AvdIndexedList[{primary_key_type}, {item_class_name}]", + item_type=item_class_name, + description=( + f"Subclass of AvdIndexedList with `{item_class_name}` items. Primary key is `{self.get_primary_key_field_name()}` (`{primary_key_type}`)." + ), + class_vars=[ClassVarSrc("_primary_key", FieldTypeHintSrc("str"), f'"{self.get_primary_key_field_name()}"')], + ) + + def get_item_classes(self) -> list[ModelSrc | ListSrc] | None: + """Returns a list of src classes for the items schema. There will only be multiple items if we have nested lists.""" + if self.schema.field_ref or not self.schema.items or self.schema.items.type not in ["dict", "list"]: + return None + + item_classes = [] + fieldsrc = self.schema.items._generate_class_src(f"{self.get_class_name()}Item") + item_classes.append(fieldsrc.cls) + if fieldsrc.item_classes: + item_classes.extend(fieldsrc.item_classes) + + return item_classes + + def get_type_hints(self) -> list[FieldTypeHintSrc]: + """Returns a list of FieldTypeHintSrc representing the type hints for this schema.""" + return [FieldTypeHintSrc(field_type=self.get_class().name)] + + def get_default(self) -> str | None: + """Returns the default value from the schema as a source code string.""" + if self.schema.default is None: + return None + default_value_as_str = str(self.schema.default).replace("'", '"') + return f"lambda cls: coerce_type({default_value_as_str}, target_type=cls)" + + def get_primary_key_field_name(self) -> str | None: + """ + Returns the name to be used for the field used as primary_key. + + Python reserved keywords or mixed case keys will get a prefix of "field_". + """ + if (primary_key := self.schema.primary_key) is None: + return None + + if iskeyword(primary_key) or not primary_key.islower(): + return f"field_{primary_key}" + + return primary_key + + def get_description(self) -> str: + descriptions = [super().get_description(), self.get_class().description] + return "\n\n".join(description for description in descriptions if description is not None) + + +class SrcGenDict(SrcGenBase): + """Provides the method "generate_class_src" used to build source code for Python classes representing the schema.""" + + schema: AvdSchemaDict + + def get_type(self) -> str: + if self.get_class() is not None: + return self.get_class_name() + return "dict" + + def get_class(self) -> ModelSrc | None: + """Returns ModelSrc for the given schema to be used for the class definition in the parent object.""" + if not self.schema.keys: + if not self.schema.field_ref: + return None + + classes, fields = [], [] + + else: + classes, fields = self.get_children_classes_and_fields() + return ModelSrc( + name=self.get_class_name(), + base_classes=self.get_base_classes(), + classes=classes, + fields=fields, + imports=self.get_imports(), + allow_extra=self.schema.allow_other_keys or False, + description="Subclass of AvdModel.", + ) + + def get_base_classes(self) -> list[str]: + """Return a list of base classes. Only used if there is an unresolved $ref in the schema.""" + if not self.schema.field_ref: + return [] + + return [generate_class_name_from_ref(self.schema.field_ref)] + + def get_imports(self) -> set[str]: + """Return a set of strings with Python imports that are needed for this class.""" + imports = set() + imports.add("from typing import Any") + if self.schema.field_ref: + schema_name = self.schema.field_ref.split("#", maxsplit=1)[0] + imports.add(f"from pyavd._{schema_name}.schema import {generate_class_name(schema_name)}") + + return imports + + def get_children_classes_and_fields(self) -> tuple[list[ModelSrc | ListSrc], list[FieldSrc]]: + """Return lists of ModelSrc and FieldSrc for any nested fields.""" + classes = [] + fields = [] + + if self.schema.keys: + for childschema in self.schema.keys.values(): + fieldsrc = childschema._generate_class_src() + if fieldsrc.field: + fields.append(fieldsrc.field) + # Reversing the order to ensure we put items before the class needing it. + if fieldsrc.item_classes: + classes.extend(reversed(fieldsrc.item_classes)) + if fieldsrc.cls: + classes.append(fieldsrc.cls) + + fields.append( + FieldSrc( + name="_custom_data", + field_type="dict", + optional=False, + type_hints=[FieldTypeHintSrc(field_type="dict[str, Any]")], + ) + ) + + return classes, fields + + def get_default(self) -> str | None: + """Returns the default value from the schema as a source code string.""" + # TODO: Improve this to assign a class instance directly instead of using coerce_type. + if self.schema.default is None: + return None + default_value_as_str = str(self.schema.default).replace("'", '"') + target_type = self.get_type_hints()[0].field_type + if target_type[0].isupper(): + return f"lambda cls: coerce_type({default_value_as_str}, target_type=cls)" + + return default_value_as_str + + def get_description(self) -> str: + descriptions = [super().get_description(), cls_src.description if (cls_src := self.get_class()) is not None else None] + return "\n\n".join(description for description in descriptions if description is not None) + + +class SrcGenRootDict(SrcGenDict): + """Provides the method "generate_class_src" used to build source code for Python classes representing the schema.""" + + def get_field(self) -> None: + """ + Returns FieldSrc for the given schema to be used for the field definition in the parent object. + + For the root dict there is no parent, so this always returns None. + """ + + def get_base_classes(self) -> list[str]: + """Return a list of base classes.""" + if self.get_class_name() == "EosDesigns": + return ["EosDesignsRootModel"] + return ["EosCliConfigGenRootModel"] + + def get_imports(self) -> set[str]: + imports = super().get_imports() + if self.get_class_name() == "EosDesigns": + imports.add("from pyavd._schema.models.eos_designs_root_model import EosDesignsRootModel") + else: + imports.add("from pyavd._schema.models.eos_cli_config_gen_root_model import EosCliConfigGenRootModel") + return imports + + def get_children_classes_and_fields(self) -> tuple[list[ModelSrc | ListSrc], list[FieldSrc]]: + """ + Return lists of ModelSrc and FieldSrc for any nested fields. + + For the EosDesigns root dict we also insert placeholders for custom structured configuration and dynamic keys. + """ + classes, fields = super().get_children_classes_and_fields() + if self.get_class_name() != "EosDesigns": + return classes, fields + + classes.extend( + [ + ModelSrc( + name="_CustomStructuredConfigurationsItem", + classes=[], + fields=[ + FieldSrc( + name="key", + field_type="str", + type_hints=[FieldTypeHintSrc(field_type="str")], + description="Complete key including prefix", + optional=False, + ), + FieldSrc( + name="value", + field_type="EosCliConfigGen", + type_hints=[FieldTypeHintSrc(field_type="EosCliConfigGen")], + description="Structured config including the suffix part of the key.", + optional=False, + ), + ], + ), + ListSrc( + name="_CustomStructuredConfigurations", + base_class="AvdIndexedList[str, _CustomStructuredConfigurationsItem]", + item_type="_CustomStructuredConfigurationsItem", + class_vars=[ClassVarSrc("_primary_key", FieldTypeHintSrc("str"), '"key"')], + ), + ] + ) + fields.append( + FieldSrc( + name="_custom_structured_configurations", + field_type="_CustomStructuredConfigurations", + type_hints=[FieldTypeHintSrc(field_type="_CustomStructuredConfigurations")], + ) + ) + if self.schema.dynamic_keys: + """ + Build a data model like this: + dynamic_keys: + _dynamic_key_maps: + - dynamic_keys_path: "node_type_keys.key" + model_key: "node_type_keys" + node_type_keys: + - key: "l2leaf" + value: NodeTypeKeysKey + } + """ + dyn_classes = [] + dyn_fields = [] + _dynamic_key_maps = [] + for dynamic_keys_path, childschema in self.schema.dynamic_keys.items(): + # dynamic_key_type will be "node_type_keys", "connected_endpoints_keys" or "network_services_keys" + if not childschema.display_name: + msg = "Schemas for dynamic_keys *must* have 'display_name' set." + raise ValueError(msg) + dynamic_key_type = childschema.display_name.replace(" ", "_").lower() + dynamic_key_model_name = generate_class_name(f"dynamic_{dynamic_key_type}") + _dynamic_key_maps.append({"dynamic_keys_path": dynamic_keys_path, "model_key": dynamic_key_type}) + fieldsrc = childschema._generate_class_src(class_name=generate_class_name(dynamic_key_type)) + # Overriding the details from the autocreated field. This way we can reuse the field definition with types and type hints + fieldsrc.field.name = "value" + fieldsrc.field.description = "Value of dynamic key" + dyn_classes.extend( + [ + ModelSrc( + name=f"{dynamic_key_model_name}Item", + # Reversing the order to ensure we put items before the class needing it. + classes=[cls for cls in [*reversed(fieldsrc.item_classes or []), fieldsrc.cls] if cls is not None], + fields=[ + FieldSrc( + name="key", + field_type="str", + type_hints=[FieldTypeHintSrc(field_type="str")], + description="Key used as dynamic key", + optional=False, + ), + fieldsrc.field, + ], + ), + ListSrc( + name=dynamic_key_model_name, + base_class=f"AvdIndexedList[str, {dynamic_key_model_name}Item]", + item_type=f"{dynamic_key_model_name}Item", + class_vars=[ClassVarSrc("_primary_key", FieldTypeHintSrc("str"), '"key"')], + ), + ] + ) + dyn_fields.append( + FieldSrc( + name=dynamic_key_type, + field_type=dynamic_key_model_name, + optional=False, + type_hints=[FieldTypeHintSrc(field_type=dynamic_key_model_name)], + description=f"Collection of dynamic '{dynamic_key_type}'.", + ) + ) + class_vars = [ + ClassVarSrc( + name="_dynamic_key_maps", + type_hint=FieldTypeHintSrc(field_type="tuple", list_item_type="dict, ..."), + description="Internal tuple of mappings from dynamic_keys_path to model_key.", + value=str(tuple(_dynamic_key_maps)), + ) + ] + + classes.append( + ModelSrc( + name="_DynamicKeys", + classes=dyn_classes, + fields=dyn_fields, + class_vars=class_vars, + description="Data models for dynamic keys.", + ) + ) + fields.append( + FieldSrc( + name="_dynamic_keys", + field_type="_DynamicKeys", + optional=False, + type_hints=[FieldTypeHintSrc(field_type="_DynamicKeys")], + description="Dynamic keys", + ) + ) + + return classes, fields diff --git a/python-avd/schema_tools/generate_classes/src_generators.py b/python-avd/schema_tools/generate_classes/src_generators.py new file mode 100644 index 00000000000..13b335d7c93 --- /dev/null +++ b/python-avd/schema_tools/generate_classes/src_generators.py @@ -0,0 +1,445 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +from __future__ import annotations + +from abc import ABC, abstractmethod +from dataclasses import dataclass +from textwrap import indent, wrap + +from schema_tools.constants import LICENSE_HEADER + +SRC_HEADER = indent(LICENSE_HEADER + "\n\n", "# ") + "from __future__ import annotations\n" + +BASE_IMPORTS = """\ +from typing import TYPE_CHECKING + +from pyavd._schema.models.avd_indexed_list import AvdIndexedList +from pyavd._schema.models.avd_list import AvdList +from pyavd._schema.models.avd_model import AvdModel + +if TYPE_CHECKING: + from pyavd._utils import Undefined, UndefinedType +""" +BASE_MODEL_NAME = "AvdModel" +INDENT = " " + + +@dataclass +class FieldSrc: + """ + Dataclass containing the elements to generate Python source code for one field. + + Use str() on the instance to render the source code. + """ + + name: str + field_type: str + type_hints: list[FieldTypeHintSrc] + key: str | None = None + description: str | None = None + optional: bool = True + default_value: str | None = None + """The default assignment source code for assigning lists or dicts as default values.""" + + def __str__(self) -> str: + """ + Render source code for one field. + + : | UndefinedType = Undefined + """ + return f"{self.field_as_class_attr()} | UndefinedType = Undefined" + + def field_as_class_attr(self) -> str: + """ + Render source code for one field without default assignment. + + Used for class attributes. + + : + """ + # Build union of multiple type hints + type_hints = " | ".join(str(type_hint) for type_hint in self.type_hints) + if self.optional and not self.default_value and "None" not in self.type_hints and self.field_type in ("str", "int", "bool", "float"): + type_hints += " | None" + + return f"{self.name}: {type_hints}" + + def _docstring(self) -> str: + """Render the content of the docstring for this field as source code.""" + docstring = "" + if self.description: + docstring += "\n".join(wrap(self.description, width=100, replace_whitespace=False)) + if self.default_value: + docstring += f"\n\nDefault value: `{self.default_value}`" + return docstring + + def get_imports(self) -> set: + """Return a set of strings with Python imports that are needed for this class.""" + imports = set() + if self.default_value and "coerce_type" in self.default_value: + imports.add("from pyavd._schema.coerce_type import coerce_type") + for type_hint in self.type_hints: + imports.update(type_hint.get_imports()) + return imports + + def field_as_dict_str(self) -> str: + """ + Return a representation of the field to be inserted in a dict string. + + Used for _fields classvar + """ + dict_fields_src = [f'"type": {self.field_type}'] + if self.default_value: + dict_fields_src.append(f'"default": {self.default_value}') + + return f'"{self.name}": {{{", ".join(dict_fields_src)}}}' + + +@dataclass +class ClassVarSrc: + """ + Dataclass containing the elements to generate Python source code for one ClassVar. + + Use str() on the instance to render the source code. + """ + + name: str + type_hint: FieldTypeHintSrc + value: str + description: str | None = None + """The default assignment source code for assigning lists or dicts as default values.""" + + def __str__(self) -> str: + """ + Render source code for one field. + + : ClassVar[] = + """ + return f"{self.name}: ClassVar[{self.type_hint!s}] = {self.value}" + + def _docstring(self) -> str: + """Render the content of the docstring for this field as source code.""" + if not self.description: + return "" + + docstring = "\n".join(wrap(self.description, width=100, replace_whitespace=False)) + return f"{docstring}\n" + + def get_imports(self) -> set: + imports = {"from typing import ClassVar"} + imports.update(self.type_hint.get_imports()) + return imports + + +@dataclass +class ModelSrc: + """ + Dataclass containing the elements to generate Python source code for this class including any nested classes and fields. + + Can have nested classes and fields. + + Use str() on the instance to render the source code. + """ + + name: str + classes: list[ModelSrc | ListSrc] + fields: list[FieldSrc] + class_vars: list[ClassVarSrc] | None = None + imports: set[str] | None = None + base_classes: list[str] | None = None + description: str | None = None + allow_extra: bool = False + + def __str__(self) -> str: + """Renders the Python source code for this class including any nested classes and fields.""" + base_classes = ", ".join(self.base_classes) if self.base_classes else BASE_MODEL_NAME + + classsrc = f"class {self.name}({base_classes}):\n" if base_classes else f"class {self.name}:\n" + + if self.description: + description = "\n".join(wrap(self.description, width=100, replace_whitespace=False)) + if "\n" in description: + classsrc += indent(f'"""\n{description.strip()}\n"""\n', INDENT) + else: + classsrc += indent(f'"""{description}"""\n', INDENT) + + if classes := self._render_classes(): + classsrc += f"{classes}\n" + + if class_vars := self._render_class_vars(): + classsrc += f"{class_vars}\n" + + if fields := self._render_fields(): + classsrc += f"{fields}\n" + + if not classes and not fields: + classsrc += " pass\n" + + return classsrc + + def _init_docstring(self) -> str: + """Render the docstring for the __init__ method for this model as source code.""" + docstring_elements = [f"{self.name}.\n"] + if self.description: + # Build docstring styled description + docstring_elements.append("\n".join(wrap(self.description, width=100, replace_whitespace=False))) + + if self.fields: + args = "Args:\n" + for field in self.fields: + field_arg = f"{field.name}" + if field.description: + description = ( + "\n".join(wrap(field.description, width=100, replace_whitespace=False)) + .replace("Example:\n", "Example: # fmt: skip\n") + .replace("Examples:\n", "Examples: # fmt: skip\n") + .replace("Note:\n", "Note: # fmt: skip\n") + .replace("Notes:\n", "Notes: # fmt: skip\n") + ) + if "\n" in description: + field_arg += f":\n{indent(description, ' ')}" + else: + field_arg += f": {description}" + else: + field_arg += f": {field.name}" + args += indent(field_arg, INDENT) + args += "\n" + docstring_elements.append(args) + + if docstring_elements: + docstring_content = "\n\n".join(docstring_elements) + return indent(f'"""\n{docstring_content}\n"""\n', INDENT) + return "" + + def _render_classes(self) -> str: + """Renders the Python source code for any nested classes.""" + if not self.classes: + return "" + + return indent("\n".join(str(cls) for cls in self.classes), INDENT) + + def _render_class_vars(self) -> str: + """Renders the Python source code for any ClassVars.""" + if not self.class_vars: + return "" + + return indent("\n".join(str(class_var) for class_var in self.class_vars), INDENT) + + def _render_fields(self) -> str: + """Renders the Python source code for any nested fields.""" + if not self.fields: + return "" + + fields_types_dict = ", ".join(field.field_as_dict_str() for field in self.fields) + src = f" _fields: ClassVar[dict] = {{{fields_types_dict}}}\n" + + if field_to_key_map := {field.name: field.key for field in self.fields if field.name and field.key and field.name != field.key}: + src += f" _field_to_key_map: ClassVar[dict] = {field_to_key_map}\n" + + if key_to_field_map := {field.key: field.name for field in self.fields if field.name and field.key and field.name != field.key}: + src += f" _key_to_field_map: ClassVar[dict] = {key_to_field_map}\n" + + if self.allow_extra: + src += " _allow_other_keys: ClassVar[bool] = True\n" + if not self.fields: + return src + + for field in self.fields: + src += indent(f"{field.field_as_class_attr()}\n", INDENT) + if docstring := field._docstring().strip(): + if "\n" in docstring: + src += indent(f'"""\n{docstring}\n"""\n', INDENT) + else: + src += indent(f'"""{docstring}"""\n', INDENT) + if self.base_classes == ["object"]: + # This is some internal class so we don't need __init__ + return src + + field_as_args = ["self", "*", *(str(field).split("\n", maxsplit=1)[0] for field in self.fields)] + src += indent("\n\nif TYPE_CHECKING:\n", INDENT) + src += indent(f"def __init__({', '.join(field_as_args)}) -> None:\n", INDENT * 2) + src += indent(self._init_docstring(), INDENT * 2) + return src + + def get_imports(self) -> set: + """Returns Python import statements required for this class including any nested classes and fields.""" + imports = self.imports or set() + if self.fields: + imports.add("from typing import ClassVar") + if self.class_vars: + for class_var in self.class_vars: + imports.update(class_var.get_imports()) + for cls in self.classes: + imports.update(cls.get_imports()) + for field in self.fields: + imports.update(field.get_imports()) + return imports + + +@dataclass +class ListSrc: + """ + Dataclass containing the elements to generate Python source code for this class. + + Use str() on the instance to render the source code. + """ + + name: str + base_class: str + item_type: str | None = None + class_vars: list[ClassVarSrc] | None = None + imports: set[str] | None = None + description: str | None = None + + def __str__(self) -> str: + """Renders the Python source code for this class including any nested classes and fields.""" + classsrc = f"class {self.name}({self.base_class}):\n" + + if self.description: + description = "\n".join(wrap(self.description, width=100, replace_whitespace=False)) + if "\n" in description: + classsrc += indent(f'"""\n{description.strip()}\n"""\n', INDENT) + else: + classsrc += indent(f'"""{description}"""\n', INDENT) + + if class_vars := self._render_class_vars(): + classsrc += f"{class_vars}\n" + + if not (self.description or class_vars): + classsrc += " pass\n" + + if self.item_type: + classsrc += f"\n{self.name}._item_type = {self.item_type}\n" + + return classsrc + + def _render_class_vars(self) -> str: + """Renders the Python source code for any ClassVars.""" + if not self.class_vars: + return "" + + return indent("\n".join(str(class_var) for class_var in self.class_vars), INDENT) + + def get_imports(self) -> set: + """Returns Python import statements required for this class including any nested classes and fields.""" + imports = self.imports or set() + if self.class_vars: + for class_var in self.class_vars: + imports.update(class_var.get_imports()) + return imports + + +@dataclass +class SrcData: + """Dataclass containing a field and an associated class for one schema field including child fields.""" + + field: FieldSrc | None = None + """ + field should be set on all instances except for the root model + """ + + cls: ModelSrc | ListSrc | None = None + """ + cls is a full model for a 'dict' field or the main class for a 'list' field. + """ + + item_classes: list[ModelSrc | ListSrc] | None = None + """ + item_classes is a list of Models uses as items in lists. If there are multiple classes here it is because the first one is also a list. + """ + + +@dataclass +class FileSrc: + """ + Dataclass containing the elements to generate Python source code for this file. + + Use str() on the instance to render the source code. + """ + + classes: list[ModelSrc] + + def __str__(self) -> str: + """Returns Python source code for this file.""" + src = f"{SRC_HEADER}" + # BASE_IMPORTS comes last since we have if TYPE_CHECKING. + src += f"{self._render_imports()}\n{BASE_IMPORTS}\n\n" + src += self._render_classes() + return src.rstrip() + "\n" + + def _render_classes(self) -> str: + """Render the python source code for classes.""" + return "\n\n".join(str(cls) for cls in self.classes) + + def _render_imports(self) -> str: + """Render the python source code for imports.""" + imports = set() + for cls in self.classes: + imports.update(cls.get_imports()) + return "\n".join(str(imp) for imp in imports) + + +@dataclass +class AnnotationSrc(ABC): + """ + Base class for generating python source code for one annotation. + + Subclasses must implement __str__() and get_imports(). + """ + + @abstractmethod + def __str__(self) -> str: + pass + + @abstractmethod + def get_imports(self) -> set: + pass + + +@dataclass +class FieldTypeHintSrc(AnnotationSrc): + """ + Dataclass containing the type and any annotations for one dataclass field. + + The annotations can either be a string, a subclass of AnnotationSrc or another FieldTypeHintSrc. + For field_type=="list" there list_item_type can be a string or another FieldTypeHintSrc. + """ + + field_type: str + list_item_type: str | FieldTypeHintSrc | None = None + annotations: list[str | AnnotationSrc] | None = None + + def __str__(self) -> str: + """ + Returns Python source code for type hint and optional annotation for one dataclass field. + + If there are types but no annotations given it will render " | " + If there are annotations as well as types it will render "Annotated[ | , , ]" + If there are nested annotations it could look like "Annotated[, Annotated[, ]]" + """ + field_type = f"{self.field_type}[{self.list_item_type}]" if self.field_type in ("list", "tuple") else self.field_type + + if not self.annotations: + return field_type + + return f"Annotated[{field_type}, {', '.join(str(annotation) for annotation in self.annotations)}]" + + def get_imports(self) -> set: + """Returns Python import statements required for this type hint and annotations.""" + imports = set() + if self.field_type == "list" and self.list_item_type in [None, "Any"]: + imports.add("from typing import Any") + + if "Literal[" in self.field_type: + imports.add("from typing import Literal") + + if not self.annotations: + return imports + + imports.add("from typing import Annotated") + for annotation in self.annotations: + if isinstance(annotation, AnnotationSrc): + imports.update(annotation.get_imports()) + + return imports diff --git a/python-avd/schema_tools/generate_classes/utils.py b/python-avd/schema_tools/generate_classes/utils.py new file mode 100644 index 00000000000..1101e466daa --- /dev/null +++ b/python-avd/schema_tools/generate_classes/utils.py @@ -0,0 +1,43 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. + + +def generate_class_name(class_key: str) -> str: + """ + Generate ClassName in from class_key. + + "some_key_using_snake_case" => "SomeKeyUsingSnakeCase" + """ + return "".join(element.capitalize() for element in class_key.split("_")) + + +def generate_class_name_from_ref(ref: str) -> str: + """ + Generate ClassName in from a schema ref. + + "eos_cli_config_gen#/keys/ethernet_interfaces/items" => "EosCliConfigGen.EthernetInterfacesItem" + "eos_cli_config_gen#/keys/router_bgp/keys/vlans/items => "EosCliConfigGen.RouterBgp.VlansItem" + """ + if "#" not in ref: + msg = "Schema tooling only works with fully qualified refs with '#' like 'eos_cli_config_gen#/'" + raise ValueError(msg) + + # Replacing ref with only the part after # + ref_schema, ref = ref.split("#", maxsplit=1) + + base_class_elements = [generate_class_name(ref_schema)] + + ref_elements = ref.split("/") + for ref_index, ref_element in enumerate(ref_elements): + if ref_element in {"", "keys", "items"}: + continue + + if len(ref_elements) > ref_index + 1 and ref_elements[ref_index + 1] == "items": + class_name = generate_class_name(f"{ref_element}_Item") + else: + class_name = generate_class_name(ref_element) + + base_class_elements.append(class_name) + + return ".".join(base_class_elements) diff --git a/python-avd/schema_tools/metaschema/meta_schema_model.py b/python-avd/schema_tools/metaschema/meta_schema_model.py index 8f625c2426d..4ffb87562cd 100644 --- a/python-avd/schema_tools/metaschema/meta_schema_model.py +++ b/python-avd/schema_tools/metaschema/meta_schema_model.py @@ -10,6 +10,7 @@ from pydantic import BaseModel, ConfigDict, Field, constr +from schema_tools.generate_classes.class_src_gen import SrcGenBase, SrcGenBool, SrcGenDict, SrcGenInt, SrcGenList, SrcGenRootDict, SrcGenStr from schema_tools.generate_docs.tablerowgen import TableRow, TableRowGenBase, TableRowGenBool, TableRowGenDict, TableRowGenInt, TableRowGenList, TableRowGenStr from schema_tools.generate_docs.yamllinegen import YamlLine, YamlLineGenBase, YamlLineGenBool, YamlLineGenDict, YamlLineGenInt, YamlLineGenList, YamlLineGenStr @@ -18,6 +19,8 @@ if TYPE_CHECKING: from collections.abc import Generator + from schema_tools.generate_classes.src_generators import SrcData + """ This module provides Pydantic models (classes) representing the meta-schema of the AVD Schema. @@ -104,6 +107,8 @@ class DocumentationOptions(BaseModel): # Type of schema docs generators to use for this schema field. _table_row_generator: type[TableRowGenBase] _yaml_line_generator: type[YamlLineGenBase] + # Type of class source generator to use for this schema field. + _class_src_generator: type[SrcGenBase] # Internal attributes used by schema docs generators _key: str | None = None @@ -122,23 +127,21 @@ class DocumentationOptions(BaseModel): """ # Signal to __init__ if the $ref in the schema should be resolved before initializing the pydantic model. - _resolve_schema: ClassVar[bool] = True + _resolve_schema: ClassVar[Literal["eos_designs", "eos_cli_config_gen", "all"] | None] = "all" - def __init__(self, resolve_schema: bool | None = None, **data: dict) -> None: + def __init__(self, _resolve_schema: Literal["eos_designs", "eos_cli_config_gen", "all"] | None = None, **data: Any) -> None: """ - Overrides BaseModel.__init__. - - Takes a kwarg "resolve_schema" which controls if all subclasses of AvdSchemaBaseModel should expand any $ref in the input schema. + Takes a kwarg "_resolve_schema" which controls if $refs are resolved, and if a string, only the given schema will be resolved. The $ref expansion _only_ covers this field. Any $ref on child fields are expanded as they are initialized by Pydantic since they are based on this base class. """ # Setting the resolve_schema attribute on the class, so all sub-classes will inherit this automatically. - if resolve_schema is not None: - AvdSchemaBaseModel._resolve_schema = resolve_schema + if _resolve_schema is not None: + AvdSchemaBaseModel._resolve_schema = _resolve_schema if self._resolve_schema: - data = merge_schema_from_ref(data) + data = merge_schema_from_ref(data, resolve_schema=self._resolve_schema) super().__init__(**data) @@ -214,6 +217,15 @@ def _generate_yaml_lines(self, target_table: str | None = None) -> Generator[Yam # Using the Type of yaml line generator set in the subclass attribute _yaml_line_generator yield from self._yaml_line_generator().generate_yaml_lines(schema=self, target_table=target_table) + def _generate_class_src(self, class_name: str | None = None) -> SrcData: + """ + Returns one instance of "Src" to be used for generating python class models based on the schemas. + + The function is called recursively inside the SrcGen classes for parsing children. + """ + # Using the Type of yaml line generator set in the subclass attribute _yaml_line_generator + return self._class_src_generator().generate_class_src(schema=self, class_name=class_name) + class AvdSchemaInt(AvdSchemaBaseModel): """ @@ -253,6 +265,8 @@ class ConvertType(str, Enum): # Type of schema docs generators to use for this schema field. _table_row_generator = TableRowGenInt _yaml_line_generator = YamlLineGenInt + # Type of class source generator to use for this schema field. + _class_src_generator = SrcGenInt class AvdSchemaBool(AvdSchemaBaseModel): @@ -288,6 +302,8 @@ class ConvertType(str, Enum): # Type of schema docs generators to use for this schema field. _table_row_generator = TableRowGenBool _yaml_line_generator = YamlLineGenBool + # Type of class source generator to use for this schema field. + _class_src_generator = SrcGenBool class AvdSchemaStr(AvdSchemaBaseModel): @@ -350,6 +366,8 @@ def __str__(self) -> str: # Type of schema docs generators to use for this schema field. _table_row_generator = TableRowGenStr _yaml_line_generator = YamlLineGenStr + # Type of class source generator to use for this schema field. + _class_src_generator = SrcGenStr class AvdSchemaList(AvdSchemaBaseModel): @@ -404,6 +422,8 @@ class ConvertType(str, Enum): # Type of schema docs generators to use for this schema field. _table_row_generator = TableRowGenList _yaml_line_generator = YamlLineGenList + # Type of class source generator to use for this schema field. + _class_src_generator = SrcGenList @cached_property def _descendant_tables(self) -> set[str]: @@ -508,6 +528,8 @@ class DocumentationOptions(AvdSchemaBaseModel.DocumentationOptions): # Type of schema docs generators to use for this schema field. _table_row_generator = TableRowGenDict _yaml_line_generator = YamlLineGenDict + # Type of class source generator to use for this schema field. + _class_src_generator = SrcGenDict @cached_property def _descendant_tables(self) -> set[str]: @@ -560,6 +582,9 @@ class AristaAvdSchema(AvdSchemaDict): This is the schema root dict class providing specific fields and overrides of AvdSchemaDict. """ + # Type of class source generator to use for this schema field. + _class_src_generator = SrcGenRootDict + # Internal attributes used by schema docs generators @cached_property def _table(self) -> str | None: diff --git a/python-avd/schema_tools/metaschema/resolvemodel.py b/python-avd/schema_tools/metaschema/resolvemodel.py index 1b721e0be86..9b4cd5455cc 100644 --- a/python-avd/schema_tools/metaschema/resolvemodel.py +++ b/python-avd/schema_tools/metaschema/resolvemodel.py @@ -5,26 +5,30 @@ from copy import deepcopy from functools import lru_cache +from typing import Literal from deepmerge import conservative_merger from schema_tools.store import create_store -def merge_schema_from_ref(schema: dict) -> dict: +def merge_schema_from_ref(schema: dict, resolve_schema: Literal["eos_designs", "eos_cli_config_gen", "all"] | None = None) -> dict: """ Returns a copy of the schema with any $ref resolved. If the referenced schema also has a $ref, that too will be resolved. Any child schemas will _not_ be resolved. + + By setting "resolve_schema" to a string it is possible to only resolve $refs to this schema. + If $refs are overridden with anything like extra keys etc it will still be resolved. """ if "$ref" not in schema: return schema schema = deepcopy(schema) - ref = schema.pop("$ref") - ref_schema = merge_schema_from_ref(get_schema_from_ref(ref)) + ref: str = schema["$ref"] + ref_schema = merge_schema_from_ref(get_schema_from_ref(ref), resolve_schema) if ref_schema["type"] != schema["type"]: # TODO: Consider if this should be a pyavd specific error msg = ( @@ -33,6 +37,20 @@ def merge_schema_from_ref(schema: dict) -> dict: ) raise ValueError(msg) + pure_ref_schema = ( + {"type", "$ref", "description", "documentation_options", "deprecation"}.issuperset(schema.keys()) + and resolve_schema not in [None, "all"] + and not schema["$ref"].startswith(f"{resolve_schema}#") + ) + + # If this is a pure ref schema we will not resolve it unless it is a native list. + # This ensures that the generated classes will use the class created in the ref. + # Some lists can be built as an AvdIndexedList, so we don't have to resolve it. + if pure_ref_schema and (schema["type"] != "list" or (ref_schema.get("primary_key") and not ref_schema.get("allow_duplicate_primary_key"))): + schema.setdefault("description", ref_schema.get("description")) + return schema + + schema.pop("$ref") return conservative_merger.merge(schema, ref_schema) @@ -43,7 +61,7 @@ def get_schema_from_ref(ref: str) -> dict: The ref is in the style "schema_name#/path/to/schema/element" """ - schema_store = create_store() + schema_store = create_store(load_from_yaml=True) if "#" not in ref: msg = "Missing # in ref" @@ -51,7 +69,7 @@ def get_schema_from_ref(ref: str) -> dict: schema_name, ref = ref.split("#", maxsplit=1) if schema_name not in schema_store: - msg = f"Invalid schema name '{schema_name}'" + msg = f"Invalid schema name '{schema_name}' from $ref '{ref}'" raise KeyError(msg) schema = schema_store[schema_name] diff --git a/python-avd/tests/pyavd/j2filters/test_decrypt.py b/python-avd/tests/pyavd/j2filters/test_decrypt.py index ef7ecfe7bbc..7c8962cb80d 100644 --- a/python-avd/tests/pyavd/j2filters/test_decrypt.py +++ b/python-avd/tests/pyavd/j2filters/test_decrypt.py @@ -3,6 +3,7 @@ # that can be found in the LICENSE file. from __future__ import annotations +from contextlib import AbstractContextManager from contextlib import nullcontext as does_not_raise import pytest @@ -15,7 +16,14 @@ [ pytest.param("dummy", None, "dummy", {}, pytest.raises(TypeError), id="Missing Type"), pytest.param("dummy", "eigrp", "dummy", {}, pytest.raises(KeyError), id="Wrong Type"), - pytest.param("3QGcqpU2YTwKh2jVQ4Vj/A==", "bgp", "42.42.42.42", {}, does_not_raise(), id="Implemented Type BGP"), + pytest.param( + "3QGcqpU2YTwKh2jVQ4Vj/A==", + "bgp", + "42.42.42.42", # NOSONAR, IP is just test data + {}, + does_not_raise(), + id="Implemented Type BGP", + ), pytest.param("qCTcuwOSntAmLZaW2QjKcA==", "ospf_simple", "Ethernet1", {}, does_not_raise(), id="Implemented Type OSPF simple"), pytest.param( "tDvJjUyf8///ktvy/xpfeQ==", @@ -27,7 +35,7 @@ ), ], ) -def test_decrypt(password: str, passwd_type: str | None, key: str, kwargs: dict, expected_raise: object) -> None: +def test_decrypt(password: str, passwd_type: str | None, key: str, kwargs: dict, expected_raise: AbstractContextManager) -> None: """Test decrypt method for non existing and existing type.""" with expected_raise: decrypt(password, passwd_type=passwd_type, key=key, **kwargs) diff --git a/python-avd/tests/pyavd/j2filters/test_encrypt.py b/python-avd/tests/pyavd/j2filters/test_encrypt.py index 05858e32521..9c17a88a898 100644 --- a/python-avd/tests/pyavd/j2filters/test_encrypt.py +++ b/python-avd/tests/pyavd/j2filters/test_encrypt.py @@ -3,6 +3,7 @@ # that can be found in the LICENSE file. from __future__ import annotations +from contextlib import AbstractContextManager from contextlib import nullcontext as does_not_raise import pytest @@ -15,13 +16,27 @@ [ pytest.param("dummy", None, "dummy", {}, pytest.raises(TypeError), id="Missing Type"), pytest.param("dummy", "eigrp", "dummy", {}, pytest.raises(KeyError), id="Wrong Type"), - pytest.param(42, "bgp", "42.42.42.42", {}, does_not_raise(), id="Password is not a string"), - pytest.param("arista", "bgp", "42.42.42.42", {}, does_not_raise(), id="Implemented Type BGP"), + pytest.param( + 42, + "bgp", + "42.42.42.42", # NOSONAR, IP is just test data + {}, + does_not_raise(), + id="Password is not a string", + ), + pytest.param( + "arista", + "bgp", + "42.42.42.42", # NOSONAR, IP is just test data + {}, + does_not_raise(), + id="Implemented Type BGP", + ), pytest.param("arista", "ospf_simple", "Ethernet1", {}, does_not_raise(), id="Implemented Type OSPF simple"), pytest.param("arista", "ospf_message_digest", "Ethernet1", {"hash_algorithm": "sha512", "key_id": 66}, does_not_raise(), id="Implemented Type OSPF MD"), ], ) -def test_encrypt(password: str | int, passwd_type: str | None, key: str, kwargs: dict, expected_raise: object) -> None: +def test_encrypt(password: str | int, passwd_type: str | None, key: str, kwargs: dict, expected_raise: AbstractContextManager) -> None: """Test encrypt method for non-existing and existing type.""" with expected_raise: encrypt(password, passwd_type=passwd_type, key=key, **kwargs) diff --git a/python-avd/tests/pyavd/j2filters/test_natural_sort.py b/python-avd/tests/pyavd/j2filters/test_natural_sort.py index a05b27123c9..6e313e75ede 100644 --- a/python-avd/tests/pyavd/j2filters/test_natural_sort.py +++ b/python-avd/tests/pyavd/j2filters/test_natural_sort.py @@ -2,6 +2,7 @@ # Use of this source code is governed by the Apache License 2.0 # that can be found in the LICENSE file. +from contextlib import AbstractContextManager from contextlib import nullcontext as does_not_raise from typing import Any @@ -32,7 +33,15 @@ def test_convert(self, item_to_convert: str, converted_item: int | str, ignore_c pytest.param({}, "", False, True, [], does_not_raise(), id="empty-dict"), pytest.param("", "", False, True, [], does_not_raise(), id="empty-string"), pytest.param("access_list", None, False, True, ["_", "a", "c", "c", "e", "i", "l", "s", "s", "s", "t"], does_not_raise(), id="string-input"), - pytest.param(["1,2,3,4", "11,2,3,4", "5.6.7.8"], None, False, True, ["1,2,3,4", "5.6.7.8", "11,2,3,4"], does_not_raise(), id="list-of-integers"), + pytest.param( + ["1,2,3,4", "11,2,3,4", "5.6.7.8"], # NOSONAR, IP is just test data + None, + False, + True, + ["1,2,3,4", "5.6.7.8", "11,2,3,4"], # NOSONAR, IP is just test data + does_not_raise(), + id="list-of-integers", + ), pytest.param({"a1": 123, "a10": 333, "a2": 2, "a11": 4456}, None, False, True, ["a1", "a2", "a10", "a11"], does_not_raise(), id="dict"), pytest.param( [ @@ -137,7 +146,13 @@ def test_convert(self, item_to_convert: str, converted_item: int | str, ignore_c ], ) def test_natural_sort( - self, item_to_natural_sort: Any, sort_key: str | None, strict: bool | None, ignore_case: bool | None, sorted_list: list | None, expected_raise: object + self, + item_to_natural_sort: Any, + sort_key: str | None, + strict: bool, + ignore_case: bool, + sorted_list: list | None, + expected_raise: AbstractContextManager, ) -> None: with expected_raise: resp = natural_sort(item_to_natural_sort, sort_key, strict=strict, ignore_case=ignore_case) diff --git a/python-avd/tests/pyavd/j2filters/test_range_expand.py b/python-avd/tests/pyavd/j2filters/test_range_expand.py index 6803835bbcc..8a5ae8c1221 100644 --- a/python-avd/tests/pyavd/j2filters/test_range_expand.py +++ b/python-avd/tests/pyavd/j2filters/test_range_expand.py @@ -11,8 +11,8 @@ from pyavd.j2filters import range_expand RANGE_TO_EXPAND_INVALID_VALUES = [ - pytest.param(True, TypeError, "value must be of type list or str, got ", id="Wrong input type - bool"), - pytest.param({"key": "value"}, TypeError, "value must be of type list or str, got ", id="Wrong input type - dict"), + pytest.param(True, TypeError, "value must be a Sequence, got ", id="Wrong input type - bool"), + pytest.param({"key": "value"}, TypeError, "value must be a Sequence, got ", id="Wrong input type - dict"), pytest.param(33, TypeError, "", id="Wrong input type - int"), pytest.param( "Ethernet4-2", diff --git a/python-avd/tests/pyavd/molecule_scenarios/test_eos_cli_config_gen_class.py b/python-avd/tests/pyavd/molecule_scenarios/test_eos_cli_config_gen_class.py new file mode 100644 index 00000000000..f89d849e608 --- /dev/null +++ b/python-avd/tests/pyavd/molecule_scenarios/test_eos_cli_config_gen_class.py @@ -0,0 +1,77 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +import warnings +from copy import deepcopy + +import pytest + +from pyavd._eos_cli_config_gen.schema import EosCliConfigGen +from pyavd._schema.store import create_store +from tests.models import MoleculeHost + +SCHEMA = create_store()["eos_cli_config_gen"] + + +@pytest.mark.molecule_scenarios( + "eos_designs_unit_tests", + "eos_designs_deprecated_vars", + "eos_designs_l2l2", + "eos_designs-mpls-isis-sr-ldp", + # TODO: "eos_designs-twodc-5stage-clos", # Remove inline jinja + "evpn_underlay_ebgp_overlay_ebgp", + "evpn_underlay_isis_overlay_ibgp", + "evpn_underlay_ospf_overlay_ebgp", + "evpn_underlay_rfc5549_overlay_ebgp", + "example-campus-fabric", + # TODO: "example-cv-pathfinder", # Work around Ansible vault + "example-dual-dc-l3ls", + "example-isis-ldp-ipvpn", + "example-l2ls-fabric", + "example-single-dc-l3ls", + "eos_cli_config_gen", + "eos_cli_config_gen_deprecated_vars", +) +def test_eos_cli_config_gen_initialize_dict_with_valid_data(molecule_host: MoleculeHost) -> None: + """Test EosCliConfigGen model with valid data.""" + if molecule_host.scenario.name.startswith("eos_cli_config_gen"): + structured_config = deepcopy(molecule_host.hostvars) + else: + structured_config = deepcopy(molecule_host.structured_config) + + # If nothing raises, the model is accepted. + with warnings.catch_warnings(): + warnings.simplefilter("error") + EosCliConfigGen._from_dict(structured_config) + + +@pytest.mark.molecule_scenarios( + "eos_designs_unit_tests", + "eos_designs_deprecated_vars", + "eos_designs_l2l2", + "eos_designs-mpls-isis-sr-ldp", + # TODO: "eos_designs-twodc-5stage-clos", # Remove inline jinja + "evpn_underlay_ebgp_overlay_ebgp", + "evpn_underlay_isis_overlay_ibgp", + "evpn_underlay_ospf_overlay_ebgp", + "evpn_underlay_rfc5549_overlay_ebgp", + "example-campus-fabric", + # TODO: "example-cv-pathfinder", # Work around Ansible vault + "example-dual-dc-l3ls", + "example-isis-ldp-ipvpn", + "example-l2ls-fabric", + "example-single-dc-l3ls", + "eos_cli_config_gen", + "eos_cli_config_gen_deprecated_vars", +) +def test_eos_cli_config_gen_initialize_kwargs_with_valid_data(molecule_host: MoleculeHost) -> None: + """Test EosCliConfigGen model with valid data.""" + if molecule_host.scenario.name.startswith("eos_cli_config_gen"): + structured_config = deepcopy(molecule_host.hostvars) + else: + structured_config = deepcopy(molecule_host.structured_config) + + # If nothing raises, the model is accepted. + with warnings.catch_warnings(): + warnings.simplefilter("error") + EosCliConfigGen(**structured_config) diff --git a/python-avd/tests/pyavd/molecule_scenarios/test_eos_designs_class.py b/python-avd/tests/pyavd/molecule_scenarios/test_eos_designs_class.py new file mode 100644 index 00000000000..40b7eb0b4b2 --- /dev/null +++ b/python-avd/tests/pyavd/molecule_scenarios/test_eos_designs_class.py @@ -0,0 +1,121 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +import warnings +from copy import deepcopy + +import pytest + +from pyavd._eos_cli_config_gen.schema import EosCliConfigGen +from pyavd._eos_designs.schema import EosDesigns +from pyavd._schema.store import create_store +from tests.models import MoleculeHost + +SCHEMA = create_store()["eos_designs"] + +CSC_DATA = { + "fabric_name": "test", + "custom_structured_configuration_router_bgp": {"as": 123}, + "csc_loopback_interfaces": [{"name": "Loopback0"}], +} + +CSC_TESTS = [ + # prefix, expected_data + ( + None, + EosDesigns._CustomStructuredConfigurations( + [ + EosDesigns._CustomStructuredConfigurationsItem( + key="custom_structured_configuration_router_bgp", value=EosCliConfigGen(router_bgp=EosCliConfigGen.RouterBgp(field_as="123")) + ) + ] + ), + ), # Notice the auto conversion to string. + ( + ["csc_"], + EosDesigns._CustomStructuredConfigurations( + [ + EosDesigns._CustomStructuredConfigurationsItem( + key="csc_loopback_interfaces", + value=EosCliConfigGen(loopback_interfaces=EosCliConfigGen.LoopbackInterfaces([EosCliConfigGen.LoopbackInterfacesItem(name="Loopback0")])), + ) + ] + ), + ), +] + + +@pytest.mark.parametrize(("prefix", "expected_data"), CSC_TESTS) +def test_eos_designs_custom_structured_configuration(prefix: str | None, expected_data: dict) -> None: + data = CSC_DATA.copy() + if prefix: + data.update({"custom_structured_configuration_prefix": prefix}) + loaded_model = EosDesigns._from_dict(data) + assert hasattr(loaded_model, "_custom_structured_configurations") + assert isinstance(loaded_model._custom_structured_configurations, EosDesigns._CustomStructuredConfigurations) + + for entry in loaded_model._custom_structured_configurations: + assert isinstance(entry, EosDesigns._CustomStructuredConfigurationsItem) + + assert loaded_model._custom_structured_configurations == expected_data + + +# eos_cli_config_gen inputs are validated by `validate_structured_config` in another file. +@pytest.mark.molecule_scenarios( + "eos_designs_unit_tests", + "eos_designs_deprecated_vars", + "eos_designs_l2l2", + "eos_designs-mpls-isis-sr-ldp", + "eos_designs-twodc-5stage-clos", + "evpn_underlay_ebgp_overlay_ebgp", + "evpn_underlay_isis_overlay_ibgp", + "evpn_underlay_ospf_overlay_ebgp", + "evpn_underlay_rfc5549_overlay_ebgp", + "example-campus-fabric", + # TODO: "example-cv-pathfinder", # Work around Ansible vault + "example-dual-dc-l3ls", + "example-isis-ldp-ipvpn", + "example-l2ls-fabric", + "example-single-dc-l3ls", +) +def test_eos_designs_initialize_kwargs_with_valid_data(molecule_host: MoleculeHost) -> None: + """Test EosDesigns model with valid data.""" + inputs = deepcopy(molecule_host.hostvars) + + # The class will not accept _custom_keys to be given directly. They must be given as `_custom_data: `. + # This is normally handled by the loader, but since we here test loading with kwargs, we need to remove any + # custom keys from the test data. + inputs = {k: v for k, v in inputs.items() if not str(k).startswith("_")} + + # If nothing raises, the model is accepted. + with warnings.catch_warnings(): + warnings.simplefilter("error") + EosDesigns(**inputs) + + +# eos_cli_config_gen inputs are validated by `validate_structured_config` in another file. +@pytest.mark.molecule_scenarios( + "eos_designs_unit_tests", + "eos_designs_deprecated_vars", + "eos_designs_l2l2", + "eos_designs-mpls-isis-sr-ldp", + "eos_designs-twodc-5stage-clos", + "evpn_underlay_ebgp_overlay_ebgp", + "evpn_underlay_isis_overlay_ibgp", + "evpn_underlay_ospf_overlay_ebgp", + "evpn_underlay_rfc5549_overlay_ebgp", + "example-campus-fabric", + # TODO: "example-cv-pathfinder", # Work around Ansible vault + "example-dual-dc-l3ls", + "example-isis-ldp-ipvpn", + "example-l2ls-fabric", + "example-single-dc-l3ls", +) +def test_eos_designs_initialize_dict_with_valid_data(molecule_host: MoleculeHost) -> None: + """Test EosDesigns model with valid data.""" + inputs = deepcopy(molecule_host.hostvars) + + # If nothing raises, the model is accepted. + with warnings.catch_warnings(): + warnings.simplefilter("error") + EosDesigns._from_dict(inputs) diff --git a/python-avd/tests/pyavd/molecule_scenarios/test_validate_structured_config.py b/python-avd/tests/pyavd/molecule_scenarios/test_validate_structured_config.py index b5b90f11a92..7beb160d735 100644 --- a/python-avd/tests/pyavd/molecule_scenarios/test_validate_structured_config.py +++ b/python-avd/tests/pyavd/molecule_scenarios/test_validate_structured_config.py @@ -29,10 +29,16 @@ "example-isis-ldp-ipvpn", "example-l2ls-fabric", "example-single-dc-l3ls", + "eos_cli_config_gen", + "eos_cli_config_gen_deprecated_vars", ) def test_validate_structured_config_with_valid_data(molecule_host: MoleculeHost) -> None: """Test validate_structured_config.""" - structured_config = deepcopy(molecule_host.structured_config) + if molecule_host.scenario.name.startswith("eos_cli_config_gen"): + structured_config = deepcopy(molecule_host.hostvars) + else: + structured_config = deepcopy(molecule_host.structured_config) + validation_result = validate_structured_config(structured_config) assert validation_result.validation_errors == [] assert validation_result.failed is False @@ -44,7 +50,10 @@ def test_validate_structured_config_with_valid_data(molecule_host: MoleculeHost) ) def test_validate_structured_config_with_invalid_data(molecule_host: MoleculeHost) -> None: """Test validate_structured_config.""" - structured_config = deepcopy(molecule_host.structured_config) + if molecule_host.scenario.name.startswith("eos_cli_config_gen"): + structured_config = deepcopy(molecule_host.hostvars) + else: + structured_config = deepcopy(molecule_host.structured_config) updated = False # Insert a bad key in a random dict (making sure the dict is covered by the schema) @@ -64,43 +73,3 @@ def test_validate_structured_config_with_invalid_data(molecule_host: MoleculeHos assert len(validation_result.validation_errors) >= 1 assert isinstance(validation_result.validation_errors[0], AvdValidationError) assert "invalid_key" in str(validation_result.validation_errors[0]) - - -@pytest.mark.molecule_scenarios( - "eos_cli_config_gen", - "eos_cli_config_gen_deprecated_vars", -) -def test_validate_cli_gen_inputs_with_valid_data(molecule_host: MoleculeHost) -> None: - """Test validate_structured_config.""" - inputs = deepcopy(molecule_host.hostvars) - validation_result = validate_structured_config(inputs) - assert validation_result.validation_errors == [] - assert validation_result.failed is False - - -@pytest.mark.molecule_scenarios( - "eos_cli_config_gen", - "eos_cli_config_gen_deprecated_vars", -) -def test_validate_cli_gen_inputs_with_invalid_data(molecule_host: MoleculeHost) -> None: - """Test validate_structured_config.""" - inputs = deepcopy(molecule_host.hostvars) - - updated = False - # Insert a bad key in a random dict (making sure the dict is covered by the schema) - for key, value in inputs.items(): - if not isinstance(value, dict) or key not in SCHEMA["keys"]: - continue - value.update({"invalid_key": "some_value"}) - updated = True - break - - # No dict found, so we insert our own instead - if not updated: - inputs.update({"router_bgp": {"invalid_key": "some_value"}}) - - validation_result = validate_structured_config(inputs) - assert validation_result.failed is True - assert len(validation_result.validation_errors) >= 1 - assert isinstance(validation_result.validation_errors[0], AvdValidationError) - assert "invalid_key" in str(validation_result.validation_errors[0]) diff --git a/python-avd/tests/pyavd/utils/password/test_password.py b/python-avd/tests/pyavd/utils/password/test_password.py index a717f2afdfb..efb0effafc3 100644 --- a/python-avd/tests/pyavd/utils/password/test_password.py +++ b/python-avd/tests/pyavd/utils/password/test_password.py @@ -21,16 +21,16 @@ ########## BGP_INPUT_DICT_ENCRYPT_EXPECTED = [ - ("42.42.42.42", "arista", "3QGcqpU2YTwKh2jVQ4Vj/A=="), + ("42.42.42.42", "arista", "3QGcqpU2YTwKh2jVQ4Vj/A=="), # NOSONAR, IP is just test data ("AVD-TEST", "arista", "bM7t58t04qSqLHAfZR/Szg=="), ] # password used is "arista" BGP_VALID_INPUT_DICT_DECRYPT_EXPECTED = [ - ("42.42.42.42", "3QGcqpU2YTwKh2jVQ4Vj/A==", "arista"), + ("42.42.42.42", "3QGcqpU2YTwKh2jVQ4Vj/A==", "arista"), # NOSONAR, IP is just test data ("AVD-TEST", "bM7t58t04qSqLHAfZR/Szg==", "arista"), ] BGP_INVALID_INPUT_DICT_DECRYPT = [ - ("10.42.42.43", "3QGcqpU2YTwKh2jVQ4Vj/A=="), + ("10.42.42.43", "3QGcqpU2YTwKh2jVQ4Vj/A=="), # NOSONAR, IP is just test data ("AVD-TEST-DUMMY", "bM7t58t04qSqLHAfZR/Szg=="), ] # The following list uses all the molecule BGP passwords available @@ -39,8 +39,8 @@ BGP_MOLECULE_PASSWORDS_TEST = [ ("UNDERLAY-PEERS", "arista123", "0nsCUm70mvSTxVO0ldytrg=="), ("UNDERLAY_PEERS", "arista123", "af6F4WLl4wUrWRZcwbEwkQ=="), - ("123.1.1.10", "arista123", "oBztv71m2uhR7hh58/OCNA=="), - ("123.1.1.11", "arista123", "oBztv71m2uhR7hh58/OCNA=="), + ("123.1.1.10", "arista123", "oBztv71m2uhR7hh58/OCNA=="), # NOSONAR, IP is just test data + ("123.1.1.11", "arista123", "oBztv71m2uhR7hh58/OCNA=="), # NOSONAR, IP is just test data ("MPLS-IBGP-PEERS", "arista123", "mWV4B6WpLCfOTyKATLWuBg=="), ("EVPN-OVERLAY-RS-PEERS", "arista123", "dRx9sULvl+hzkCMYJLEQCw=="), ("EVPN-OVERLAY", "arista123", "MY+KbyJy4kSu+X/blnVwsg=="), @@ -49,8 +49,8 @@ ("IPV6-UNDERLAY-MLAG", "arista123", "CXS0NveSYzQRmm6SRGp42w=="), ("IPV4-UNDERLAY-MLAG", "arista123", "46jF9S9T7v5RRceVzhrlBg=="), ("MPLS-OVERLAY-PEERS", "arista123", "SHsTgDgjVUU5a9blyxSt3Q=="), - ("192.168.48.1", "arista123", "toZKiUFLVUTU4hdS5V8F4Q=="), - ("192.168.48.3", "arista123", "OajzUG59/YF0NkgvOQyRnQ=="), + ("192.168.48.1", "arista123", "toZKiUFLVUTU4hdS5V8F4Q=="), # NOSONAR, IP is just test data + ("192.168.48.3", "arista123", "OajzUG59/YF0NkgvOQyRnQ=="), # NOSONAR, IP is just test data ("MLAG-PEERS", "arista123", "15AwQNBEJ1nyF/kBEtoAGw=="), ("OVERLAY-PEERS", "arista123", "64fqSH5CFUNLRHErezMrRg=="), ("RR-OVERLAY-PEERS", "arista123", "04FdfTXWrEfpDTUc3mlSjg=="), diff --git a/python-avd/tests/pyavd/utils/password/test_password_utils.py b/python-avd/tests/pyavd/utils/password/test_password_utils.py index 1e14da92a07..97c5c139e31 100644 --- a/python-avd/tests/pyavd/utils/password/test_password_utils.py +++ b/python-avd/tests/pyavd/utils/password/test_password_utils.py @@ -8,19 +8,25 @@ from pyavd._utils.password_utils.password_utils import cbc_check_password, cbc_decrypt, cbc_encrypt # password used is "arista" -VALID_PASSWORD_KEY_PAIRS = [("42.42.42.42", b"3QGcqpU2YTwKh2jVQ4Vj/A=="), ("AVD-TEST", b"bM7t58t04qSqLHAfZR/Szg==")] -INVALID_PASSWORD_KEY_PAIRS = [("10.42.42.43", b"3QGcqpU2YTwKh2jVQ4Vj/A=="), ("AVD-TEST-DUMMY", b"bM7t58t04qSqLHAfZR/Szg==")] +VALID_PASSWORD_KEY_PAIRS = [ + ("42.42.42.42", b"3QGcqpU2YTwKh2jVQ4Vj/A=="), # NOSONAR, IP is just test data + ("AVD-TEST", b"bM7t58t04qSqLHAfZR/Szg=="), +] +INVALID_PASSWORD_KEY_PAIRS = [ + ("10.42.42.43", b"3QGcqpU2YTwKh2jVQ4Vj/A=="), # NOSONAR, IP is just test data + ("AVD-TEST-DUMMY", b"bM7t58t04qSqLHAfZR/Szg=="), +] @pytest.mark.parametrize(("key", "expected"), VALID_PASSWORD_KEY_PAIRS) -def test_cbc_encrypt(key: str, expected: str) -> None: +def test_cbc_encrypt(key: str, expected: bytes) -> None: """Valid cases for both neighbor IP and peer group name.""" augmented_key = bytes(f"{key}_passwd", encoding="utf-8") assert cbc_encrypt(augmented_key, b"arista") == expected @pytest.mark.parametrize(("key", "password"), VALID_PASSWORD_KEY_PAIRS) -def test_cbc_decrypt(key: str, password: str) -> None: +def test_cbc_decrypt(key: str, password: bytes) -> None: """Valid cases for both neighbor IP and peer group name.""" augmented_key = bytes(f"{key}_passwd", encoding="utf-8") assert cbc_decrypt(augmented_key, password) == b"arista" @@ -32,7 +38,7 @@ def test_cbc_decrypt(key: str, password: str) -> None: pytest.param("TOTO", b"3QGcqpU2YTwKh2jVQ4Vj/A==", ValueError, id="ValueError"), ], ) -def test_cbc_decrypt_failure(key: str, password: str, expected_raise: Exception) -> None: +def test_cbc_decrypt_failure(key: str, password: bytes, expected_raise: type[Exception]) -> None: """Valid cases for both neighbor IP and peer group name.""" augmented_key = bytes(f"{key}_passwd", encoding="utf-8") with pytest.raises(expected_raise): @@ -40,14 +46,14 @@ def test_cbc_decrypt_failure(key: str, password: str, expected_raise: Exception) @pytest.mark.parametrize(("key", "password"), VALID_PASSWORD_KEY_PAIRS) -def test_cbc_check_password_success(key: str, password: str) -> None: +def test_cbc_check_password_success(key: str, password: bytes) -> None: """Valid cases for both neighbor IP and peer group name.""" augmented_key = bytes(f"{key}_passwd", encoding="utf-8") assert cbc_check_password(augmented_key, password) is True @pytest.mark.parametrize(("key", "password"), INVALID_PASSWORD_KEY_PAIRS) -def test_cbc_check_password_invalid_values(key: str, password: str) -> None: +def test_cbc_check_password_invalid_values(key: str, password: bytes) -> None: """Invalid cases for both neighbor IP and peer group name.""" augmented_key = bytes(f"{key}_passwd", encoding="utf-8") assert cbc_check_password(augmented_key, password) is False diff --git a/python-avd/tests/schema_tools/artifacts/DC1-BL1A.json b/python-avd/tests/schema_tools/artifacts/DC1-BL1A.json new file mode 100644 index 00000000000..2f0674739a1 --- /dev/null +++ b/python-avd/tests/schema_tools/artifacts/DC1-BL1A.json @@ -0,0 +1,5032 @@ +{ + "root_dir": "/home/holbech/avd/python-avd/scripts", + "eos_designs_documentation": { + "enable": false + }, + "eos_cli_config_gen_documentation": { + "enable": false + }, + "fabric_name": "EOS_DESIGNS_UNIT_TESTS", + "trunk_groups": { + "mlag_l3": { + "name": "LEAF_PEER_L3" + } + }, + "default_network_ports_description": "", + "default_network_ports_port_channel_description": "{adapter_description_or_endpoint?}{endpoint_port_channel?<_}", + "default_connected_endpoints_description": "{endpoint}{endpoint_port?<_}", + "default_connected_endpoints_port_channel_description": "{adapter_description_or_endpoint}{endpoint_port_channel?<_}", + "mlag_member_description": "MLAG_PEER_{mlag_peer}_{interface}", + "mlag_port_channel_description": "MLAG_PEER_{mlag_peer}_Po{mlag_port_channel_id}", + "mlag_peer_svi_description": "MLAG_PEER", + "mlag_peer_l3_svi_description": "MLAG_PEER_L3_PEERING", + "mlag_peer_vlan_name": "MLAG_PEER", + "mlag_peer_l3_vlan_name": "LEAF_PEER_L3", + "mlag_peer_l3_vrf_svi_description": "MLAG_PEER_L3_iBGP: vrf {vrf}", + "mlag_peer_l3_vrf_vlan_name": "MLAG_iBGP_{vrf}", + "mlag_bgp_peer_description": "{mlag_peer}", + "overlay_bgp_peer_description": "{peer}", + "default_underlay_p2p_ethernet_description": "P2P_LINK_TO_{peer!u}_{peer_interface}{vrf?<_vrf_}", + "default_underlay_p2p_port_channel_description": "P2P_LINK_TO_{peer}_{peer_interface}", + "underlay_l2_ethernet_description": "{peer!u}_{peer_interface}", + "underlay_l2_port_channel_description": "{peer_node_group_or_uppercase_peer}_Po{peer_port_channel_id}", + "default_vrf_diag_loopback_description": "{vrf}_VTEP_DIAGNOSTICS", + "mlag_bgp_peer_group_description": "MLAG_PEER_{mlag_peer}", + "local_users": [ + { + "name": "admin", + "disabled": true, + "privilege": 15, + "role": "network-admin", + "no_password": true + }, + { + "name": "cvpadmin", + "privilege": 15, + "role": "network-admin", + "sha512_password": "$6$rZKcbIZ7iWGAWTUM$TCgDn1KcavS0s.OV8lacMTUkxTByfzcGlFlYUWroxYuU7M/9bIodhRO7nXGzMweUxvbk8mJmQl8Bh44cRktUj.", + "ssh_key": "ssh-rsa AAAAB3NzaC1yc2EAA82spi2mkxp4FgaLi4CjWkpnL1A/MD7WhrSNgqXToF7QCb9Lidagy9IHafQxfu7LwkFdyQIMu8XNwDZIycuf29wHbDdz1N+YNVK8zwyNAbMOeKMqblsEm2YIorgjzQX1m9+/rJeFBKz77PSgeMp/Rc3txFVuSmFmeTy3aMkU= cvpadmin@hostmachine.local", + "secondary_ssh_key": "ssh-rsa AAAAB3NzaC1yc2EAA82spi2mkxp4FgaLi4CjWkpnL1A/MD7WhrSNgqXToF7QCb9Lidagy9IHafQxfu7LwkFdyQIMu8XNwDZIycuf29wHbDdz1N+YNVK8zwyNAbMOeKMqblsEm2YIorgjzQX1m9+/rJeFBKz77PSgeMp/Rc3txFVuSmFmeTy3aMkz= cvpadmin@hostmachine.local" + } + ], + "cvp_instance_ips": [ + "192.168.200.11" + ], + "cvp_ingestauth_key": "", + "terminattr_disable_aaa": false, + "snmp_settings": { + "contact": "example@example.com", + "location": true + }, + "mgmt_gateway": "192.168.200.5", + "name_servers": [ + "192.168.200.5", + "8.8.8.8", + "2001:db8::1", + "2001:db8::2" + ], + "management_eapi": { + "enable_https": true, + "default_services": false + }, + "ntp_settings": { + "server_vrf": "use_mgmt_interface_vrf", + "servers": [ + { + "name": "192.168.200.5" + }, + { + "name": "2001:db8::3" + } + ] + }, + "default_interfaces": [ + { + "types": [ + "spine" + ], + "platforms": [ + "7280R3", + "default" + ], + "uplink_interfaces": [ + "Ethernet49-54/1" + ], + "mlag_interfaces": [ + "Ethernet55-56/1" + ], + "downlink_interfaces": [ + "Ethernet1-32/1" + ] + }, + { + "types": [ + "spine" + ], + "platforms": [ + "7[58]00R3", + "7500R" + ], + "uplink_interfaces": [ + "Ethernet1/31-34/1" + ], + "mlag_interfaces": [ + "Ethernet1/35-36/1" + ], + "downlink_interfaces": [ + "Ethernet1/1-30/1" + ] + }, + { + "types": [ + "spine", + "l3leaf" + ], + "platforms": [ + "7050[SC]X3" + ], + "uplink_interfaces": [ + "Ethernet49-52/1" + ], + "mlag_interfaces": [ + "Ethernet53-54/1" + ], + "downlink_interfaces": [ + "Ethernet1-30/1" + ] + }, + { + "types": [ + "l3leaf", + "spine" + ], + "platforms": [ + "VEOS", + "vEOS", + "vEOS.*", + "VEOS.*" + ], + "uplink_interfaces": [ + "Ethernet27-34" + ], + "mlag_interfaces": [ + "Ethernet35-36" + ], + "downlink_interfaces": [ + "Ethernet1-26" + ] + }, + { + "types": [ + "l3leaf" + ], + "platforms": [ + "default" + ], + "uplink_interfaces": [ + "Ethernet49-52/1" + ], + "mlag_interfaces": [ + "Ethernet53-54/1" + ], + "downlink_interfaces": [ + "Ethernet1-30/1" + ] + }, + { + "types": [ + "l3leaf" + ], + "platforms": [ + "7280R", + "7280R2", + "my_custom_platform" + ], + "uplink_interfaces": [ + "Ethernet49-56/1" + ], + "mlag_interfaces": [ + "Ethernet57-58/1" + ], + "downlink_interfaces": [ + "Ethernet1-30/1" + ] + }, + { + "types": [ + "l3leaf" + ], + "platforms": [ + "7368.*" + ], + "uplink_interfaces": [ + "Ethernet1/9-14/1" + ], + "mlag_interfaces": [ + "Ethernet1/15-16/1" + ], + "downlink_interfaces": [ + "Ethernet1/1-8/1" + ] + }, + { + "types": [ + "l3leaf" + ], + "platforms": [ + "7300X3" + ], + "uplink_interfaces": [ + "Ethernet1/27-30/1" + ], + "mlag_interfaces": [ + "Ethernet1/31-32/1" + ], + "downlink_interfaces": [ + "Ethernet1/1-26/1" + ] + } + ], + "custom_platform_settings": [ + { + "platforms": [ + "my_custom_platform" + ], + "management_interface": "Management42", + "tcam_profile": "vxlan-routing", + "lag_hardware_only": true, + "reload_delay": { + "mlag": 900, + "non_mlag": 1020 + }, + "feature_support": { + "queue_monitor_length_notify": false, + "interface_storm_control": false, + "bgp_update_wait_for_convergence": true, + "bgp_update_wait_install": true + } + }, + { + "platforms": [ + "7280R" + ], + "management_interface": "Management99", + "tcam_profile": "vxlan-routing", + "lag_hardware_only": true, + "reload_delay": { + "mlag": 900, + "non_mlag": 1020 + } + } + ], + "shutdown_interfaces_towards_undeployed_peers": true, + "shutdown_bgp_towards_undeployed_peers": true, + "evpn_vlan_aware_bundles": true, + "evpn_hostflap_detection": { + "expiry_timeout": 10 + }, + "bgp_peer_groups": { + "ipv4_underlay_peers": { + "name": "UNDERLAY-PEERS", + "password": "0nsCUm70mvSTxVO0ldytrg==" + }, + "evpn_overlay_peers": { + "password": "q+VNViP5i4rVjW1cxFv2wA==" + }, + "mlag_ipv4_underlay_peer": { + "name": "MLAG-PEERS", + "password": "15AwQNBEJ1nyF/kBEtoAGw==" + }, + "ipvpn_gateway_peers": { + "name": "IPVPN-INTERWORKING-PEERS", + "password": "nWwwZQLPI34O1AhoANg77g==" + } + }, + "spine_platform": "7050SX3", + "spine_bgp_defaults": [ + "distance bgp 20 200 200" + ], + "spine": { + "defaults": { + "platform": "7050SX3", + "bgp_as": 65001, + "loopback_ipv4_pool": "192.168.255.0/24", + "bgp_defaults": [ + "distance bgp 20 200 200" + ] + }, + "nodes": [ + { + "name": "DC1-SPINE1", + "id": 1, + "mgmt_ip": "192.168.200.101/24", + "mac_address": "0c:1d:c0:1d:62:01" + }, + { + "name": "DC1-SPINE2", + "platform": "7500R", + "id": 2, + "mgmt_ip": "192.168.200.102/24", + "mac_address": "0c:1d:c0:1d:62:01" + }, + { + "name": "DC1-SPINE3", + "platform": "7800R3", + "id": 3, + "mgmt_ip": "192.168.200.103/24", + "mac_address": "0c:1d:c0:1d:62:01" + }, + { + "name": "DC1-SPINE4", + "platform": "7280R3", + "id": 4, + "mgmt_ip": "192.168.200.104/24", + "mac_address": "0c:1d:c0:1d:62:01" + } + ] + }, + "l3leaf": { + "defaults": { + "max_parallel_uplinks": 2, + "loopback_ipv4_pool": "192.168.255.0/24", + "loopback_ipv4_offset": 8, + "vtep_loopback_ipv4_pool": "192.168.254.0/24", + "uplink_switches": [ + "DC1-SPINE1", + "DC1-SPINE2", + "DC1-SPINE3", + "DC1-SPINE4" + ], + "max_uplink_switches": 8, + "uplink_ipv4_pool": "172.31.254.0/23", + "uplink_interface_speed": "forced 100gfull", + "bgp_defaults": [ + "distance bgp 20 200 200" + ], + "platform": "7280R", + "bgp_as": 65101, + "mlag_interfaces_speed": "100g", + "mlag_peer_l3_vlan": 4090, + "mlag_peer_vlan": 4092, + "mlag_peer_link_allowed_vlans": "1-4094", + "spanning_tree_mode": "mstp", + "spanning_tree_root_super": true, + "spanning_tree_priority": 4096, + "virtual_router_mac_address": "00:dc:00:00:00:0a", + "filter": { + "tenants": [ + "Tenant_A", + "Tenant_B", + "Tenant_C", + "Tenant_D" + ], + "tags": [ + "opzone", + "web", + "app", + "db", + "vmotion", + "nfs", + "v6wan", + "v6opzone" + ] + }, + "mlag_peer_l3_ipv4_pool": "10.255.251.0/24", + "mlag_peer_ipv4_pool": "10.255.252.0/24" + }, + "node_groups": [ + { + "group": "DC1_LEAF1", + "platform": "VEOS", + "filter": { + "tenants": [ + "all" + ], + "tags": [ + "web", + "app", + "erp2", + "v6wan" + ] + }, + "nodes": [ + { + "name": "DC1-LEAF1A", + "id": 1, + "rack": "rackA", + "mgmt_ip": "192.168.200.105/24", + "mac_address": "0c:1d:c0:1d:62:01", + "loopback_ipv4_address": "192.168.42.42", + "vtep_loopback_ipv4_address": "192.168.43.43" + } + ] + }, + { + "group": "DC1_LEAF2", + "bgp_as": 65102, + "rack": "rackD", + "mlag": false, + "uplink_switches": [ + "DC1-SPINE1", + "DC1-SPINE2", + "DC1-SPINE2", + "DC1-SPINE1", + "DC1-SPINE3", + "DC1-SPINE4", + "DC1-SPINE4", + "DC1-SPINE3" + ], + "nodes": [ + { + "name": "DC1-LEAF2A", + "id": 2, + "rack": "rackC", + "mgmt_ip": "192.168.200.106/24", + "mac_address": "0c:1d:c0:1d:62:01" + }, + { + "name": "DC1-LEAF2B", + "id": 3, + "mgmt_ip": "192.168.200.107/24" + } + ] + }, + { + "group": "DC1_SVC3", + "platform": "7050SX3", + "bgp_as": 65103, + "mlag_port_channel_id": 2000, + "mlag_domain_id": "custom_mlag_domain_id", + "filter": { + "tenants": [ + "Tenant_A", + "Tenant_B", + "Tenant_C" + ], + "tags": [ + "opzone", + "web", + "app", + "db", + "vmotion", + "nfs", + "wan" + ] + }, + "nodes": [ + { + "name": "DC1-SVC3A", + "id": 4, + "mgmt_ip": "192.168.200.108/24", + "mac_address": "0c:1d:c0:1d:62:01" + }, + { + "name": "DC1-SVC3B", + "id": 5, + "mgmt_ip": "192.168.200.109/24" + } + ] + }, + { + "group": "DC1_BL1", + "uplink_interfaces": [ + "Ethernet1", + "Ethernet2", + "Ethernet3", + "Ethernet4" + ], + "mlag": false, + "filter": { + "tenants": [ + "all" + ], + "tags": [ + "wan" + ], + "always_include_vrfs_in_tenants": [ + "Tenant_B" + ] + }, + "structured_config": { + "sflow": { + "vrfs": [ + { + "name": "OOB", + "destinations": [ + { + "destination": "192.168.200.10" + }, + { + "destination": "10.0.200.90" + } + ], + "source_interface": "Management99" + } + ] + } + }, + "nodes": [ + { + "name": "DC1-BL1A", + "id": 6, + "bgp_as": 65104, + "mgmt_ip": "192.168.200.110/24", + "mac_address": "0c:1d:c0:1d:62:01", + "uplink_switch_interfaces": [ + "Ethernet22", + "Ethernet22", + "Ethernet22", + "Ethernet22" + ], + "evpn_gateway": { + "remote_peers": [ + { + "hostname": "DC1-BL2A" + }, + { + "hostname": "DC1-BL2B", + "ip_address": "192.168.42.42", + "bgp_as": 65042 + } + ], + "evpn_l2": { + "enabled": true + }, + "evpn_l3": { + "enabled": true, + "inter_domain": true + } + } + }, + { + "name": "DC1-BL1B", + "id": 7, + "bgp_as": 65105, + "mgmt_ip": "192.168.200.111/24", + "mac_address": "0c:1d:c0:1d:62:01", + "uplink_switch_interfaces": [ + "Ethernet23", + "Ethernet23", + "Ethernet23", + "Ethernet23" + ], + "evpn_gateway": { + "remote_peers": [ + { + "hostname": "MY_EVPN_GW1_USER_DEFINED", + "ip_address": "1.1.1.1", + "bgp_as": 65555 + }, + { + "hostname": "MY_EVPN_GW2_USER_DEFINED", + "ip_address": "2.2.2.2", + "bgp_as": 65555 + } + ], + "evpn_l2": { + "enabled": true + }, + "evpn_l3": { + "enabled": true, + "inter_domain": false + } + } + } + ] + }, + { + "group": "DC1_BL2", + "uplink_interfaces": [ + "Ethernet1", + "Ethernet2", + "Ethernet3", + "Ethernet4" + ], + "mlag": false, + "ipvpn_gateway": { + "enabled": true, + "evpn_domain_id": "65000:3", + "ipvpn_domain_id": "65000:4", + "maximum_routes": 50000, + "local_as": 65001, + "address_families": [ + "vpn-ipv4", + "vpn-ipv6" + ], + "remote_peers": [ + { + "hostname": "rr1", + "ip_address": "100.70.0.1", + "bgp_as": 64512 + }, + { + "hostname": "rr2", + "ip_address": "100.70.0.2", + "bgp_as": 64512 + } + ] + }, + "filter": { + "tenants": [ + "all" + ], + "tags": [ + "wan" + ], + "always_include_vrfs_in_tenants": [ + "Tenant_B" + ] + }, + "nodes": [ + { + "name": "DC1-BL2A", + "platform": "7280R2", + "id": 8, + "bgp_as": 65106, + "mgmt_ip": "192.168.200.117/24", + "mac_address": "0c:1d:c0:1d:62:01", + "uplink_switch_interfaces": [ + "Ethernet24", + "Ethernet24", + "Ethernet24", + "Ethernet24" + ] + }, + { + "name": "DC1-BL2B", + "platform": "7280R3", + "id": 9, + "bgp_as": 65107, + "mgmt_ip": "192.168.200.118/24", + "mac_address": "0c:1d:c0:1d:62:01", + "uplink_switch_interfaces": [ + "Ethernet25", + "Ethernet25", + "Ethernet25", + "Ethernet25" + ] + } + ] + }, + { + "group": "DC1_CL1", + "mlag": true, + "uplink_interfaces": [ + "Ethernet1", + "Ethernet2", + "Ethernet3", + "Ethernet4" + ], + "evpn_services_l2_only": true, + "filter": { + "tenants": [ + "Tenant_A", + "Tenant_B", + "Tenant_C" + ], + "tags": [ + "opzone", + "web", + "app", + "db", + "vmotion", + "nfs", + "wan" + ] + }, + "nodes": [ + { + "name": "DC1-CL1A", + "platform": "7368X4", + "id": 10, + "bgp_as": 65108, + "mgmt_ip": "192.168.200.119/24", + "uplink_switch_interfaces": [ + "Ethernet26", + "Ethernet26", + "Ethernet26", + "Ethernet26" + ], + "mlag_ibgp_origin_incomplete": false + }, + { + "name": "DC1-CL1B", + "platform": "7300X3", + "id": 11, + "bgp_as": 65109, + "mgmt_ip": "192.168.200.120/24", + "uplink_switch_interfaces": [ + "Ethernet27", + "Ethernet27", + "Ethernet27", + "Ethernet27" + ] + } + ] + }, + { + "group": "DC1_UNDEPLOYED_LEAF1", + "platform": "my_custom_platform", + "filter": { + "tenants": [ + "Tenant_A", + "Tenant_B", + "Tenant_C" + ], + "tags": [ + "opzone", + "web", + "app", + "db", + "vmotion", + "nfs", + "wan" + ] + }, + "nodes": [ + { + "name": "DC1_UNDEPLOYED_LEAF1A", + "id": 13, + "bgp_as": 65110, + "uplink_switch_interface_speed": "100g-2", + "mgmt_ip": "192.168.200.121/24", + "uplink_switch_interfaces": [ + "Ethernet28", + "Ethernet28", + "Ethernet28", + "Ethernet28" + ] + }, + { + "name": "DC1_UNDEPLOYED_LEAF1B", + "id": 14, + "bgp_as": 65111, + "mgmt_ip": "192.168.200.122/24", + "uplink_switch_interfaces": [ + "Ethernet29", + "Ethernet29", + "Ethernet29", + "Ethernet29" + ] + } + ] + } + ] + }, + "l2leaf": { + "defaults": { + "platform": "vEOS-LAB", + "uplink_switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "uplink_interfaces": [ + "Ethernet1", + "Ethernet2" + ], + "mlag": true, + "mlag_interfaces": [ + "Ethernet3", + "Ethernet4" + ], + "mlag_peer_vlan": 4091, + "spanning_tree_mode": "mstp", + "spanning_tree_priority": 16384, + "rack": "rackE", + "mlag_peer_l3_ipv4_pool": "10.255.251.0/24", + "mlag_peer_ipv4_pool": "10.255.252.0/24" + }, + "node_groups": [ + { + "group": "DC1_L2LEAF1", + "mlag_interfaces_speed": "forced 40gfull", + "uplink_interface_speed": "forced 10000", + "uplink_switches": [ + "DC1-LEAF2A", + "DC1-LEAF2B" + ], + "short_esi": "0808:0707:0606", + "filter": { + "tenants": [ + "Tenant_A" + ], + "tags": [ + "opzone", + "web", + "app" + ] + }, + "uplink_mtu": 1499, + "nodes": [ + { + "name": "DC1-L2LEAF1A", + "id": 8, + "mgmt_ip": "192.168.200.112/24", + "mac_address": "0c:1d:c0:1d:62:01", + "uplink_switch_interfaces": [ + "Ethernet7", + "Ethernet7" + ], + "uplink_mtu": 1498 + }, + { + "name": "DC1-L2LEAF1B", + "id": 11, + "mgmt_ip": "192.168.200.115/24", + "mac_address": "0c:1d:c0:1d:62:02", + "uplink_switch_interfaces": [ + "Ethernet8", + "Ethernet8" + ] + } + ] + }, + { + "group": "DC1_L2LEAF2", + "mlag_dual_primary_detection": true, + "uplink_interface_speed": "forced 100gfull", + "uplink_switch_interface_speed": "100g-2", + "uplink_switch_port_channel_id": 1007, + "uplink_port_channel_id": 1001, + "nodes": [ + { + "name": "DC1-L2LEAF2A", + "id": 9, + "mgmt_ip": "192.168.200.113/24", + "mac_address": "0c:1d:c0:1d:62:01", + "uplink_switch_interfaces": [ + "Ethernet7", + "Ethernet7" + ] + }, + { + "name": "DC1-L2LEAF2B", + "id": 10, + "mgmt_ip": "192.168.200.114/24", + "mac_address": "0c:1d:c0:1d:62:01", + "uplink_switch_interfaces": [ + "Ethernet8", + "Ethernet8" + ] + } + ] + }, + { + "group": "DC1_L2LEAF3", + "uplink_switches": [ + "DC1-LEAF2A", + "DC1-LEAF2B" + ], + "short_esi": "0606:0707:0808", + "filter": { + "tenants": [ + "Tenant_A" + ], + "tags": [ + "opzone", + "web", + "app" + ] + }, + "nodes": [ + { + "name": "DC1-L2LEAF3A", + "mgmt_ip": "192.168.200.116/24", + "mac_address": "0c:1d:c0:1d:62:01", + "uplink_switch_interfaces": [ + "Ethernet9", + "Ethernet9" + ] + } + ] + }, + { + "group": "DC1_L2LEAF4", + "uplink_switches": [ + "DC1-LEAF2A", + "DC1-LEAF2B" + ], + "short_esi": "auto", + "filter": { + "tenants": [ + "Tenant_A" + ], + "tags": [ + "opzone", + "web", + "app" + ] + }, + "nodes": [ + { + "name": "DC1-L2LEAF4A", + "id": 13, + "mgmt_ip": "192.168.200.119/24", + "uplink_switch_interfaces": [ + "Ethernet13", + "Ethernet13" + ], + "uplink_switch_port_channel_id": 1013, + "uplink_port_channel_id": 1001 + } + ] + }, + { + "group": "DC1_L2LEAF5", + "uplink_switches": [ + "DC1-LEAF2A", + "DC1-LEAF2B" + ], + "short_esi": "auto", + "filter": { + "tenants": [ + "Tenant_A" + ], + "tags": [ + "opzone", + "web", + "app" + ] + }, + "nodes": [ + { + "name": "DC1.L2LEAF5A", + "id": 14, + "mgmt_ip": "192.168.200.120/24" + }, + { + "name": "DC1.L2LEAF5B", + "id": 15, + "mgmt_ip": "192.168.200.121/24" + } + ] + }, + { + "group": "DC1_L2LEAF6", + "short_esi": "auto", + "nodes": [ + { + "name": "DC1.L2LEAF6A", + "id": 16, + "mgmt_ip": "192.168.200.122/24", + "uplink_switches": [ + "DC1-LEAF2A" + ], + "uplink_switch_interfaces": [ + "Ethernet30" + ] + }, + { + "name": "DC1.L2LEAF6B", + "id": 17, + "mgmt_ip": "192.168.200.123/24", + "uplink_switches": [ + "DC1-LEAF2B" + ], + "uplink_switch_interfaces": [ + "Ethernet31" + ] + } + ] + } + ] + }, + "p2p_uplinks_mtu": 1500, + "bfd_multihop": { + "interval": 1200, + "min_rx": 1200, + "multiplier": 3 + }, + "custom_structured_configuration_prefix": [ + "my_dci_", + "my_special_dci_", + "override_" + ], + "platform_speed_groups": [ + { + "platform": "7280R", + "speeds": [ + { + "speed": "25G", + "speed_groups": [ + 3, + 2, + "5/1" + ] + }, + { + "speed": "10G", + "speed_groups": [ + 1, + 2, + 4 + ] + } + ] + }, + { + "platform": "my_custom_platform", + "speeds": [ + { + "speed": "10G", + "speed_groups": [ + 3, + 2, + "5/1" + ] + }, + { + "speed": "25G", + "speed_groups": [ + 1, + 2, + 4 + ] + } + ] + } + ], + "boot": { + "secret": { + "key": "a153de6290ff1409257ade45f" + } + }, + "port_profiles": [ + { + "profile": "TENANT_A_B", + "mode": "trunk", + "vlans": "110-111,210-211" + }, + { + "profile": "TENANT_A", + "mode": "access", + "vlans": "110" + }, + { + "profile": "TENANT_A_MTU", + "mode": "access", + "vlans": "110", + "mtu": 1600 + }, + { + "profile": "TENANT_B", + "mode": "trunk", + "vlans": "210-211" + }, + { + "profile": "PHONE_WITH_PC", + "mode": "trunk phone", + "phone_vlan": 211, + "native_vlan": 210, + "phone_trunk_mode": "untagged" + }, + { + "profile": "ALL_WITH_SECURITY", + "mode": "trunk", + "vlans": "1-4094", + "spanning_tree_bpdufilter": "disabled", + "spanning_tree_bpduguard": "disabled", + "spanning_tree_portfast": "edge", + "l2_mtu": 8000, + "l2_mru": 9000, + "storm_control": { + "all": { + "level": 10.0, + "unit": "percent" + }, + "broadcast": { + "level": 100.0, + "unit": "pps" + }, + "multicast": { + "level": 1.5, + "unit": "percent" + }, + "unknown_unicast": { + "level": 2.8, + "unit": "percent" + } + } + }, + { + "profile": "ALL_WITH_SECURITY_PORT_CHANNEL", + "mode": "trunk", + "vlans": "1-4094", + "spanning_tree_bpdufilter": "enabled", + "spanning_tree_bpduguard": "enabled", + "spanning_tree_portfast": "edge", + "l2_mtu": 8000, + "l2_mru": 9000, + "storm_control": { + "all": { + "level": 10, + "unit": "percent" + }, + "broadcast": { + "level": 100, + "unit": "pps" + }, + "multicast": { + "level": 1, + "unit": "percent" + }, + "unknown_unicast": { + "level": 2, + "unit": "percent" + } + }, + "port_channel": { + "endpoint_port_channel": "ALL_WITH_SECURITY_PORT_CHANNEL", + "mode": "active" + } + }, + { + "profile": "ALL_WITH_SECURITY_PORT_CHANNEL_LACP_FALLBACK", + "mode": "trunk", + "vlans": "1-4094", + "spanning_tree_bpdufilter": true, + "spanning_tree_bpduguard": true, + "spanning_tree_portfast": "edge", + "l2_mtu": 8000, + "storm_control": { + "all": { + "level": 10, + "unit": "percent" + }, + "broadcast": { + "level": 100, + "unit": "pps" + }, + "multicast": { + "level": 1, + "unit": "percent" + }, + "unknown_unicast": { + "level": 2, + "unit": "percent" + } + }, + "port_channel": { + "endpoint_port_channel": "ALL_WITH_SECURITY_PORT_CHANNEL", + "mode": "active", + "lacp_fallback": { + "mode": "static", + "timeout": 10 + } + } + }, + { + "profile": "PORT_CHANNEL_LACP_TIMER", + "mode": "trunk", + "vlans": "1-4094", + "port_channel": { + "endpoint_port_channel": "PORT_CHANNEL_LACP_MODE", + "mode": "active", + "lacp_timer": { + "mode": "fast", + "multiplier": 10 + } + } + }, + { + "profile": "PORT_CHANNEL_LACP_TIMER_NORMAL", + "mode": "trunk", + "vlans": "1-4094", + "port_channel": { + "endpoint_port_channel": "PORT_CHANNEL_LACP_MODE_NORMAL", + "mode": "active", + "lacp_timer": { + "mode": "normal", + "multiplier": 100 + } + } + }, + { + "profile": "NESTED_PORT_PROFILE", + "parent_profile": "ALL_WITH_SECURITY_PORT_CHANNEL_LACP_FALLBACK", + "port_channel": { + "endpoint_port_channel": "NESTED_ALL_WITH_SECURITY_PORT_CHANNEL", + "mode": "active" + } + }, + { + "profile": "DOT1X_PORT_PROFILE", + "dot1x": { + "port_control": "auto", + "reauthentication": true, + "pae": { + "mode": "authenticator" + }, + "authentication_failure": { + "action": "allow", + "allow_vlan": 800 + }, + "host_mode": { + "mode": "multi-host", + "multi_host_authenticated": true + }, + "mac_based_authentication": { + "enabled": true + }, + "timeout": { + "reauth_period": "server", + "tx_period": 3 + }, + "reauthorization_request_limit": 3 + } + } + ], + "servers": [ + { + "name": "server01_MLAG", + "rack": "RackB", + "adapters": [ + { + "endpoint_ports": [ + "Eth2", + "Eth3" + ], + "switch_ports": [ + "Ethernet10", + "Ethernet10" + ], + "switches": [ + "DC1-LEAF2A", + "DC1-LEAF2B" + ], + "profile": "TENANT_B", + "port_channel": { + "endpoint_port_channel": "PortChanne1", + "mode": "active" + }, + "spanning_tree_bpdufilter": "disabled", + "spanning_tree_bpduguard": "disabled" + } + ] + }, + { + "name": "server01_MTU_PROFILE_MLAG", + "rack": "RackB", + "adapters": [ + { + "endpoint_ports": [ + "Eth4", + "Eth5" + ], + "switch_ports": [ + "Ethernet11", + "Ethernet11" + ], + "switches": [ + "DC1-LEAF2A", + "DC1-LEAF2B" + ], + "profile": "TENANT_A_MTU", + "port_channel": { + "endpoint_port_channel": "PortChanne1", + "mode": "active" + }, + "spanning_tree_bpdufilter": "enabled", + "spanning_tree_bpduguard": "enabled" + } + ] + }, + { + "name": "server01_MTU_ADAPTOR_MLAG", + "rack": "RackB", + "adapters": [ + { + "endpoint_ports": [ + "Eth6", + "Eth7" + ], + "switch_ports": [ + "Ethernet12", + "Ethernet12" + ], + "switches": [ + "DC1-LEAF2A", + "DC1-LEAF2B" + ], + "mtu": 1601, + "port_channel": { + "endpoint_port_channel": "PortChanne1", + "mode": "active" + }, + "spanning_tree_bpdufilter": true, + "spanning_tree_bpduguard": true + } + ] + }, + { + "name": "server02_SINGLE_NODE_TRUNK", + "rack": "RackB", + "adapters": [ + { + "endpoint_ports": [ + "Eth1" + ], + "switch_ports": [ + "Ethernet6" + ], + "switches": [ + "DC1-LEAF1A" + ], + "profile": "ALL_WITH_SECURITY", + "spanning_tree_bpdufilter": false, + "spanning_tree_bpduguard": false + } + ] + }, + { + "name": "server02_SINGLE_NODE", + "rack": "RackB", + "adapters": [ + { + "endpoint_ports": [ + "Eth1" + ], + "switch_ports": [ + "Ethernet7" + ], + "switches": [ + "DC1-LEAF1A" + ], + "profile": "TENANT_A" + } + ] + }, + { + "name": "server03_ESI", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet10", + "Ethernet10" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC4A" + ], + "profile": "TENANT_A_B", + "ethernet_segment": { + "short_esi": "0303:0202:0101" + }, + "port_channel": { + "endpoint_port_channel": "PortChanne1", + "mode": "active" + } + } + ] + }, + { + "name": "server03_ESI_L2LEAF", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet5", + "Ethernet5" + ], + "switches": [ + "DC1-L2LEAF1A", + "DC1-L2LEAF1B" + ], + "profile": "TENANT_A_B", + "ethernet_segment": { + "short_esi": "0303:0202:0101" + }, + "port_channel": { + "endpoint_port_channel": "PortChanne1", + "mode": "active" + } + } + ] + }, + { + "name": "server04_inherit_all_from_profile", + "rack": "RackC", + "adapters": [ + { + "switch_ports": [ + "Ethernet11", + "Ethernet11" + ], + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "profile": "ALL_WITH_SECURITY" + } + ] + }, + { + "name": "server05_no_profile", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet12", + "Ethernet12" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "mode": "trunk", + "vlans": "1-4094", + "spanning_tree_bpdufilter": true, + "spanning_tree_bpduguard": "disabled", + "spanning_tree_portfast": "edge", + "storm_control": { + "all": { + "level": 10, + "unit": "percent" + }, + "broadcast": { + "level": 100, + "unit": "pps" + }, + "multicast": { + "level": 1, + "unit": "percent" + }, + "unknown_unicast": { + "level": 2, + "unit": "percent" + } + } + } + ] + }, + { + "name": "server06_override_profile", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet13", + "Ethernet13" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "profile": "ALL_WITH_SECURITY", + "mode": "access", + "vlans": "210", + "spanning_tree_bpdufilter": "disabled", + "spanning_tree_bpduguard": true, + "spanning_tree_portfast": "network", + "storm_control": { + "all": { + "level": 20, + "unit": "pps" + }, + "broadcast": { + "level": 200, + "unit": "percent" + }, + "multicast": { + "level": 1, + "unit": "percent" + }, + "unknown_unicast": { + "level": 2, + "unit": "percent" + } + } + } + ] + }, + { + "name": "server07_inherit_all_from_profile_port_channel", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet14", + "Ethernet14" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "profile": "ALL_WITH_SECURITY_PORT_CHANNEL" + } + ] + }, + { + "name": "server08_no_profile_port_channel", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet15", + "Ethernet15" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "mode": "trunk", + "vlans": "1-4094", + "spanning_tree_bpdufilter": true, + "spanning_tree_bpduguard": "disabled", + "spanning_tree_portfast": "edge", + "storm_control": { + "all": { + "level": 10, + "unit": "percent" + }, + "broadcast": { + "level": 100, + "unit": "pps" + }, + "multicast": { + "level": 1, + "unit": "percent" + }, + "unknown_unicast": { + "level": 2, + "unit": "percent" + } + }, + "port_channel": { + "endpoint_port_channel": "server08_no_profile_port_channel", + "mode": "on" + } + } + ] + }, + { + "name": "server09_override_profile_no_port_channel", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet16", + "Ethernet16" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "profile": "ALL_WITH_SECURITY_PORT_CHANNEL", + "mode": "access", + "vlans": "210", + "spanning_tree_bpdufilter": "disabled", + "spanning_tree_bpduguard": true, + "spanning_tree_portfast": "network", + "storm_control": { + "all": { + "level": 20, + "unit": "pps" + }, + "broadcast": { + "level": 200, + "unit": "percent" + }, + "multicast": { + "level": 1, + "unit": "percent" + }, + "unknown_unicast": { + "level": 2, + "unit": "percent" + } + }, + "port_channel": null + } + ] + }, + { + "name": "server10_no_profile_port_channel_lacp_fallback", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet17", + "Ethernet17" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "mode": "trunk", + "vlans": "1-4094", + "spanning_tree_bpdufilter": true, + "spanning_tree_bpduguard": "disabled", + "spanning_tree_portfast": "edge", + "storm_control": { + "all": { + "level": 10, + "unit": "percent" + }, + "broadcast": { + "level": 100, + "unit": "pps" + }, + "multicast": { + "level": 1, + "unit": "percent" + }, + "unknown_unicast": { + "level": 2, + "unit": "percent" + } + }, + "port_channel": { + "endpoint_port_channel": "server10_no_profile_port_channel_lacp_fallback", + "mode": "passive", + "lacp_fallback": { + "mode": "static" + } + } + } + ] + }, + { + "name": "server11_inherit_profile_port_channel_lacp_fallback", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet18", + "Ethernet18" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "profile": "ALL_WITH_SECURITY_PORT_CHANNEL_LACP_FALLBACK" + } + ] + }, + { + "name": "server12_inherit_nested_profile_port_channel_lacp_fallback", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet19", + "Ethernet19" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "profile": "NESTED_PORT_PROFILE" + } + ] + }, + { + "name": "server13_disabled_interfaces", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet20", + "Ethernet20" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "profile": "TENANT_A", + "enabled": false + } + ] + }, + { + "name": "server14_explicitly_enabled_interfaces", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet21", + "Ethernet21" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "profile": "TENANT_A", + "enabled": true + } + ] + }, + { + "name": "server15_port_channel_with_disabled_phy_interfaces", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet22", + "Ethernet22" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "profile": "TENANT_A", + "enabled": false, + "port_channel": { + "endpoint_port_channel": "server15_port_channel_with_disabled_phy_interfaces", + "mode": "active", + "enabled": true + } + } + ] + }, + { + "name": "server16_port_channel_with_disabled_port_channel", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet23", + "Ethernet23" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "profile": "TENANT_A", + "port_channel": { + "endpoint_port_channel": "server16_port_channel_with_disabled_port_channel", + "mode": "active", + "enabled": false + } + } + ] + }, + { + "name": "server17_port_channel_with_disabled_phy_and_po_interfaces", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet24", + "Ethernet24" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "profile": "TENANT_A", + "enabled": false, + "port_channel": { + "endpoint_port_channel": "server17_port_channel_with_disabled_phy_and_po_interfaces", + "mode": "active", + "enabled": false + } + } + ] + }, + { + "name": "server18_monitoring_session_source_phys_interfaces", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet25", + "Ethernet25" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "profile": "TENANT_A", + "monitor_sessions": [ + { + "name": "MonitoringSessionServer18WithDest", + "role": "source", + "source_settings": { + "direction": "rx", + "access_group": { + "type": "ip", + "name": "MyIpACL", + "priority": 5 + } + } + }, + { + "name": "MonitoringSessionServer18WithoutDest", + "role": "source", + "source_settings": { + "direction": "tx" + } + } + ] + } + ] + }, + { + "name": "server18_monitoring_session_source_po", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth3", + "Eth4" + ], + "switch_ports": [ + "Ethernet27", + "Ethernet27" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "profile": "TENANT_A", + "enabled": true, + "port_channel": { + "endpoint_port_channel": "server18_monitoring_session_source_po", + "mode": "active", + "enabled": true + }, + "monitor_sessions": [ + { + "name": "MonitoringSessionServer18WithDest", + "role": "source", + "source_settings": { + "direction": "tx", + "access_group": { + "type": "mac", + "name": "MyMacACL", + "priority": 5 + } + } + } + ] + } + ] + }, + { + "name": "server18_monitoring_session_source_phys_interface", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth5" + ], + "switch_ports": [ + "Ethernet28" + ], + "switches": [ + "DC1-SVC3A" + ], + "profile": "TENANT_A", + "enabled": true, + "monitor_sessions": [ + { + "name": "MonitoringSessionServer18WithDest", + "role": "source", + "source_settings": { + "direction": "tx", + "access_group": { + "type": "mac", + "name": "MyMacACL", + "priority": 5 + } + } + } + ] + } + ] + }, + { + "name": "server19_monitoring_session_destination_phys", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet26", + "Ethernet26" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "monitor_sessions": [ + { + "name": "MonitoringSessionServer18WithDest", + "role": "destination", + "session_settings": { + "encapsulation_gre_metadata_tx": true, + "header_remove_size": 20, + "access_group": { + "type": "ip", + "name": "ip_acl" + }, + "rate_limit_per_ingress_chip": "30 bps", + "rate_limit_per_egress_chip": "30 bps", + "sample": 10, + "truncate": { + "enabled": true, + "size": 20 + } + } + } + ] + } + ] + }, + { + "name": "server20_monitoring_session_destination_phys", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1" + ], + "switch_ports": [ + "Ethernet40" + ], + "switches": [ + "DC1-SVC3A" + ], + "monitor_sessions": [ + { + "name": "MonitoringSessionServer18WithDest", + "role": "destination", + "session_settings": { + "encapsulation_gre_metadata_tx": false, + "header_remove_size": 200, + "access_group": { + "type": "mac", + "name": "mac_acl" + }, + "rate_limit_per_ingress_chip": "30 bps", + "rate_limit_per_egress_chip": "30 bps", + "sample": 10, + "truncate": { + "enabled": true, + "size": 20 + } + } + } + ] + } + ] + }, + { + "name": "server21_monitoring_session_destination_po", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet42", + "Ethernet42" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "profile": "TENANT_A", + "enabled": true, + "port_channel": { + "endpoint_port_channel": "server21_monitoring_session_destination_po", + "mode": "active", + "enabled": true + }, + "monitor_sessions": [ + { + "name": "MonitoringSessionServer18WithDest", + "role": "destination" + } + ] + } + ] + }, + { + "name": "server22_port_channel_with_custom_id", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet29", + "Ethernet29" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "profile": "TENANT_A", + "port_channel": { + "endpoint_port_channel": "server22_port_channel_with_custom_id", + "mode": "active", + "enabled": true, + "channel_id": 1291 + } + } + ] + }, + { + "name": "server23_phone", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "int_1" + ], + "switch_ports": [ + "Ethernet30" + ], + "switches": [ + "DC1-SVC3A" + ], + "profile": "TENANT_A", + "mode": "trunk phone", + "enabled": true + } + ] + }, + { + "name": "server24_port_channel_lacp_timer_profile", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet31", + "Ethernet31" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "profile": "PORT_CHANNEL_LACP_TIMER", + "port_channel": { + "endpoint_port_channel": "server24_port_channel_with_lacp_timer" + } + } + ] + }, + { + "name": "server25_port_channel_lacp_timer", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet32", + "Ethernet32" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "port_channel": { + "endpoint_port_channel": "server25_port_channel_with_lacp_timer", + "mode": "active", + "enabled": true, + "lacp_timer": { + "mode": "fast", + "multiplier": 5 + } + } + } + ] + }, + { + "name": "server26_port_channel_lacp_timer_profile", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet33", + "Ethernet33" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "profile": "PORT_CHANNEL_LACP_TIMER_NORMAL", + "port_channel": { + "endpoint_port_channel": "server26_port_channel_with_lacp_timer" + } + } + ] + }, + { + "name": "server27_port_channel_lacp_timer", + "rack": "RackC", + "adapters": [ + { + "endpoint_ports": [ + "Eth1", + "Eth2" + ], + "switch_ports": [ + "Ethernet34", + "Ethernet34" + ], + "switches": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "port_channel": { + "endpoint_port_channel": "server27_port_channel_with_lacp_timer", + "mode": "active", + "enabled": true, + "lacp_timer": { + "mode": "normal", + "multiplier": 50 + } + } + } + ] + } + ], + "phones": [ + { + "name": "PHONE01_untagged", + "adapters": [ + { + "endpoint_ports": [ + "Eth0" + ], + "switch_ports": [ + "Ethernet8" + ], + "switches": [ + "DC1-LEAF1A" + ], + "mode": "trunk phone", + "native_vlan": 120, + "phone_vlan": 113, + "phone_trunk_mode": "untagged" + } + ] + }, + { + "name": "PHONE02_tagged", + "adapters": [ + { + "endpoint_ports": [ + "Eth0" + ], + "switch_ports": [ + "Ethernet9" + ], + "switches": [ + "DC1-LEAF1A" + ], + "mode": "trunk phone", + "native_vlan": 120, + "phone_vlan": 113, + "phone_trunk_mode": "tagged" + } + ] + }, + { + "name": "PHONE03_port_channel", + "adapters": [ + { + "endpoint_ports": [ + "Eth0", + "Eth1" + ], + "switch_ports": [ + "Ethernet26", + "Ethernet26" + ], + "switches": [ + "DC1-LEAF2A", + "DC1-LEAF2B" + ], + "profile": "PHONE_WITH_PC", + "port_channel": { + "mode": "active", + "description": "{endpoint} Port-Channel to {endpoint_type}" + } + } + ] + } + ], + "firewalls": [ + { + "name": "FIREWALL01", + "rack": "RackB", + "adapters": [ + { + "endpoint_ports": [ + "E0", + "E1" + ], + "switch_ports": [ + "Ethernet20", + "Ethernet20" + ], + "switches": [ + "DC1-LEAF2A", + "DC1-LEAF2B" + ], + "profile": "TENANT_A_B", + "port_channel": { + "endpoint_port_channel": "PortChanne1", + "mode": "active" + } + } + ] + } + ], + "routers": [ + { + "name": "ROUTER01", + "rack": "RackB", + "adapters": [ + { + "endpoint_ports": [ + "Eth0", + "Eth1" + ], + "switch_ports": [ + "Ethernet21", + "Ethernet21" + ], + "switches": [ + "DC1-LEAF2A", + "DC1-LEAF2B" + ], + "profile": "TENANT_A" + } + ] + } + ], + "network_ports": [ + { + "switches": [ + "DC1-LEAF2A" + ], + "switch_ports": [ + "Ethernet24-25" + ], + "profile": "DOT1X_PORT_PROFILE", + "description": "PC" + } + ], + "tenant_a": [ + { + "name": "Tenant_A", + "mac_vrf_vni_base": 10000, + "mac_vrf_id_base": 20000, + "redistribute_mlag_ibgp_peering_vrfs": true, + "vrfs": [ + { + "name": "Tenant_A_OP_Zone", + "description": "Tenant_A_OP_Zone", + "vrf_vni": 10, + "vrf_id": 9, + "vtep_diagnostic": { + "loopback": 100, + "loopback_ip_range": "10.255.1.0/24" + }, + "redistribute_mlag_ibgp_peering_vrfs": false, + "svis": [ + { + "id": "110", + "name": "Tenant_A_OP_Zone_1", + "tags": [ + "opzone" + ], + "enabled": true, + "ipv4_acl_in": "TEST-IPV4-ACL-WITH-IP-FIELDS-IN", + "ipv4_acl_out": "TEST-IPV4-ACL-WITH-IP-FIELDS-OUT", + "ip_address_virtual": "10.1.10.1/24" + }, + { + "id": 111, + "vni_override": 50111, + "name": "Tenant_A_OP_Zone_2", + "tags": [ + "opzone" + ], + "enabled": true, + "ip_address_virtual": "10.1.11.1/24", + "ip_helpers": [ + { + "ip_helper": "1.1.1.1", + "source_interface": "lo100", + "source_vrf": "MGMT" + } + ] + }, + { + "id": 112, + "name": "Tenant_A_OP_Zone_3", + "profile": "DERIVED_DHCP", + "tags": [ + "opzone" + ], + "enabled": true + }, + { + "id": 113, + "name": "Tenant_A_OP_Zone_4", + "tags": [ + "DC1_LEAF1" + ], + "enabled": true, + "ospf": { + "enabled": true, + "area": 0, + "authentication": "message-digest", + "point_to_point": true, + "message_digest_keys": [ + { + "id": 1, + "hash_algorithm": "sha1", + "key": "AQQvKeimxJu+uGQ/yYvv9w==" + }, + { + "id": 2, + "key": "AQQvKeimxJu+uGQ/yYvv9w==" + } + ] + } + } + ], + "ospf": { + "enabled": true, + "nodes": [ + "DC1-LEAF1A" + ] + } + }, + { + "name": "Tenant_A_WEB_Zone", + "vrf_vni": 11, + "mlag_ibgp_peering_ipv4_pool": "172.31.11.0/24", + "svis": [ + { + "id": 120, + "name": "Tenant_A_WEB_Zone_1", + "tags": [ + "web", + "erp1" + ], + "profile": "WITH_DHCP_AND_SNOOPING", + "ip_address_virtual": "10.1.20.1/24", + "ip_address_virtual_secondaries": [ + "10.2.20.1/24", + "10.2.21.1/24" + ] + }, + { + "id": 121, + "name": "Tenant_A_WEBZone_2", + "tags": [ + "web" + ], + "profile": "GENERIC_FULL" + } + ] + }, + { + "name": "Tenant_A_APP_Zone", + "vrf_vni": 12, + "svis": [ + { + "id": 130, + "name": "Tenant_A_APP_Zone_1", + "tags": [ + "app", + "erp1" + ], + "profile": "WITH_NO_MTU", + "ip_address_virtual": "10.1.30.1/24" + }, + { + "id": 131, + "name": "Tenant_A_APP_Zone_2", + "tags": [ + "app" + ], + "enabled": true, + "ip_address_virtual": "10.1.31.1/24" + }, + { + "id": 132, + "name": "Tenant_A_APP_Zone_3", + "tags": [ + "erp2" + ], + "enabled": true, + "nodes": [ + { + "node": "DC1-LEAF1A", + "ip_address": "10.1.32.1/24" + } + ], + "ip_virtual_router_addresses": [ + "10.1.32.254", + "10.2.32.254/24", + "10.3.32.254/24" + ] + } + ] + }, + { + "name": "Tenant_A_DB_Zone", + "vrf_vni": 13, + "svis": [ + { + "id": 140, + "name": "Tenant_A_DB_BZone_1", + "tags": [ + "db", + "erp1" + ], + "enabled": true, + "ip_address_virtual": "10.1.40.1/24" + }, + { + "id": 141, + "name": "Tenant_A_DB_Zone_2", + "tags": [ + "db" + ], + "enabled": true, + "ip_address_virtual": "10.1.41.1/24" + } + ] + }, + { + "name": "Tenant_A_WAN_Zone", + "vrf_id": 14, + "ospf": { + "enabled": true, + "max_lsa": 15000, + "redistribute_bgp": { + "enabled": true + }, + "redistribute_connected": { + "enabled": true, + "route_map": "RM_TEST" + }, + "nodes": [ + "DC1-BL1A", + "DC1-BL1B" + ] + }, + "l3_interfaces": [ + { + "interfaces": [ + "Ethernet7" + ], + "ip_addresses": [ + "10.10.10.10/24" + ], + "nodes": [ + "DC1-BL1A" + ], + "mtu": 9000, + "enabled": true, + "description": "test", + "ospf": { + "enabled": true, + "area": 0, + "cost": 100, + "authentication": "message-digest", + "point_to_point": true, + "message_digest_keys": [ + { + "id": 1, + "hash_algorithm": "sha1", + "key": "AQQvKeimxJu+uGQ/yYvv9w==" + }, + { + "id": 2, + "key": "AQQvKeimxJu+uGQ/yYvv9w==" + } + ] + } + }, + { + "interfaces": [ + "Ethernet7" + ], + "ip_addresses": [ + "10.10.20.20/24" + ], + "nodes": [ + "DC1-BL1B" + ], + "mtu": 9000, + "enabled": true, + "description": "test" + } + ], + "static_routes": [ + { + "destination_address_prefix": "10.3.4.0/24", + "gateway": "1.2.3.4", + "nodes": [ + "DC1-BL1A", + "DC1-BL1B" + ] + } + ], + "bgp_peers": [ + { + "ip_address": "123.1.1.10", + "remote_as": "1234", + "password": "oBztv71m2uhR7hh58/OCNA==", + "description": "External IPv4 BGP peer", + "send_community": "standard extended", + "maximum_routes": 0, + "maximum_routes_warning_only": true, + "default_originate": { + "always": false + }, + "update_source": "Loopback123", + "ebgp_multihop": 3, + "nodes": [ + "DC1-BL1A", + "DC1-BL1B" + ], + "set_ipv4_next_hop": "123.1.1.1", + "route_map_in": "RM-123-1-1-10-IN", + "shutdown": true, + "route_map_out": "RM-123-1-1-10-OUT", + "local_as": 123 + }, + { + "ip_address": "123.1.1.11", + "remote_as": "65000.100", + "password": "oBztv71m2uhR7hh58/OCNA==", + "description": "External IPv4 BGP peer", + "send_community": "standard extended", + "maximum_routes": 0, + "default_originate": { + "always": false + }, + "update_source": "Loopback123", + "ebgp_multihop": 3, + "nodes": [ + "DC1-BL1A", + "DC1-BL1B" + ], + "route_map_in": "RM-123-1-1-11-IN", + "route_map_out": "RM-123-1-1-11-OUT", + "prefix_list_in": "PL-TEST-IN-AF4", + "prefix_list_out": "PL-TEST-OUT-AF4", + "local_as": 123, + "bfd": true + }, + { + "ip_address": "fd5a:fe45:8831:06c5::a", + "remote_as": 12345, + "send_community": "all", + "nodes": [ + "DC1-BL1A", + "DC1-BL1B" + ], + "set_ipv6_next_hop": "fd5a:fe45:8831:06c5::1", + "prefix_list_in": "PL-TEST-IN-AF6", + "prefix_list_out": "PL-TEST-OUT-AF6" + }, + { + "ip_address": "fd5a:fe45:8831:06c5::b", + "remote_as": 12345, + "nodes": [ + "DC1-BL1A", + "DC1-BL1B" + ] + } + ], + "svis": [ + { + "id": 150, + "name": "Tenant_A_WAN_Zone_1", + "tags": [ + "wan" + ], + "enabled": true, + "ip_address_virtual": "10.1.40.1/24", + "ospf": { + "enabled": true, + "area": 1, + "cost": 100, + "authentication": "simple", + "simple_auth_key": "AQQvKeimxJu+uGQ/yYvv9w==" + } + }, + { + "id": 151, + "name": "svi_with_no_tags", + "enabled": true, + "ip_address_virtual": "10.1.51.1/24" + } + ], + "additional_route_targets": [ + { + "type": "import", + "address_family": "vpn-ipv4", + "route_target": "65000:123", + "nodes": [ + "DC1-BL1A", + "DC1-BL1B", + "DC1-BL2A", + "DC1-BL2B" + ] + }, + { + "type": "export", + "address_family": "vpn-ipv4", + "route_target": "65000:123", + "nodes": [ + "DC1-BL1A", + "DC1-BL1B", + "DC1-BL2A", + "DC1-BL2B" + ] + }, + { + "type": "import", + "address_family": "evpn", + "route_target": "65000:456" + }, + { + "type": "export", + "address_family": "evpn", + "route_target": "65000:789" + } + ] + }, + { + "name": "Tenant_A_L3_VRF_Zone", + "vrf_vni": 15, + "l3_interfaces": [ + { + "interfaces": [ + "Ethernet8", + "Ethernet9", + "Ethernet8", + "Ethernet9" + ], + "ip_addresses": [ + "10.10.10.10/24", + "10.10.20.20/24", + "10.10.30.10/24", + "10.10.40.20/24" + ], + "nodes": [ + "DC1-BL1A", + "DC1-BL1A", + "DC1-BL1B", + "DC1-BL1B" + ], + "mtu": 9000, + "enabled": true, + "description": "test" + }, + { + "interfaces": [ + "Ethernet10", + "Ethernet10" + ], + "ip_addresses": [ + "10.10.30.10/24", + "10.10.40.20/24" + ], + "nodes": [ + "DC1-BL1A", + "DC1-BL1B" + ], + "mtu": 9000, + "enabled": true, + "descriptions": [ + "test-DC1-BL1A", + "test-DC1-BL1B" + ] + }, + { + "interfaces": [ + "Ethernet11", + "Ethernet11" + ], + "ip_addresses": [ + "10.10.30.10/24", + "10.10.40.20/24" + ], + "nodes": [ + "DC1-BL1A", + "DC1-BL1B" + ], + "mtu": 9000, + "enabled": true, + "description": "Single description", + "descriptions": [ + "DC1-BL1A descriptions preferred over single description", + "DC1-BL1B descriptions preferred over single description" + ] + }, + { + "interfaces": [ + "Ethernet12", + "Ethernet13.10", + "Ethernet12", + "Ethernet13.10" + ], + "ip_addresses": [ + "10.10.40.10/24", + "10.10.40.20/24", + "10.10.50.10/24", + "10.10.50.20/24" + ], + "nodes": [ + "DC1-BL1A", + "DC1-BL1A", + "DC1-BL1B", + "DC1-BL1B" + ], + "mtu": 9000, + "enabled": true, + "description": "test l3 interfaces acls", + "ipv4_acl_in": "TEST-IPV4-ACL-WITH-IP-FIELDS-IN", + "ipv4_acl_out": "TEST-IPV4-ACL-WITH-IP-FIELDS-OUT" + } + ] + }, + { + "name": "Tenant_A_OSPF", + "vrf_id": 16, + "ospf": { + "enabled": true + }, + "l3_interfaces": [ + { + "interfaces": [ + "Ethernet22", + "Ethernet24", + "Ethernet23" + ], + "ip_addresses": [ + "10.0.0.1/30", + "10.0.0.5/30", + "10.0.0.13/30" + ], + "nodes": [ + "DC1-LEAF2A", + "DC1-LEAF2B", + "DC1-LEAF2A" + ], + "ospf": { + "enabled": true, + "point_to_point": true, + "area": 0 + } + } + ], + "loopbacks": [ + { + "loopback": 123, + "ip_address": "10.1.53.0/32", + "node": "DC1-LEAF2A", + "description": "Test-Loopback", + "enabled": true, + "ospf": { + "enabled": true, + "area": 1 + } + }, + { + "loopback": 123, + "ip_address": "10.1.53.1/32", + "node": "DC1-LEAF2B", + "enabled": false, + "ospf": { + "enabled": true + }, + "raw_eos_cli": "ip ospf cost 100\n" + } + ], + "vtep_diagnostic": { + "loopback": 101, + "loopback_ip_range": "10.255.11.0/24" + } + } + ], + "l2vlans": [ + { + "id": "160", + "name": "Tenant_A_VMOTION", + "tags": [ + "opzone" + ] + }, + { + "id": 161, + "name": "Tenant_A_NFS", + "tags": [ + "opzone" + ] + }, + { + "id": 162, + "name": "l2vlan_with_no_tags" + }, + { + "id": 163, + "name": "overlapping_name" + }, + { + "id": 164, + "name": "overlapping_name" + }, + { + "id": 165, + "name": "overlapping_name" + } + ] + } + ], + "ipv4_acls": [ + { + "name": "TEST-IPV4-ACL-WITH-IP-FIELDS-IN", + "entries": [ + { + "sequence": 15, + "action": "deny", + "protocol": "ip", + "source": "any", + "destination": "interface_ip" + } + ] + }, + { + "name": "TEST-IPV4-ACL-WITH-IP-FIELDS-OUT", + "entries": [ + { + "remark": "Some remark will not require source and destination fields." + }, + { + "action": "permit", + "protocol": "ip", + "source": "interface_ip", + "destination": "any" + } + ] + } + ], + "tenant_b": [ + { + "name": "Tenant_B", + "mac_vrf_vni_base": 20000, + "vrfs": [ + { + "name": "Tenant_B_OP_Zone", + "vrf_vni": 20, + "svis": [ + { + "id": 210, + "name": "Tenant_B_OP_Zone_1", + "tags": [ + "opzone" + ], + "enabled": true, + "ip_address_virtual": "10.2.10.1/24" + }, + { + "id": 211, + "name": "Tenant_B_OP_Zone_2", + "tags": [ + "opzone" + ], + "enabled": true, + "ip_address_virtual": "10.2.11.1/24" + } + ] + }, + { + "name": "Tenant_B_WAN_Zone", + "vrf_vni": 21, + "evpn_l2_multi_domain": false, + "svis": [ + { + "id": 250, + "name": "Tenant_B_WAN_Zone_1", + "tags": [ + "wan" + ], + "enabled": true, + "ip_address_virtual": "10.2.50.1/24" + } + ] + } + ] + } + ], + "tenant_c": [ + { + "name": "Tenant_C", + "mac_vrf_vni_base": 30000, + "evpn_l2_multi_domain": false, + "bgp_peer_groups": [ + { + "name": "Tenant_C_BGP_PEER_GROUP", + "remote_as": "666", + "description": "Tenant C peer group", + "send_community": "all", + "next_hop_self": true, + "maximum_routes": 1000, + "address_family_ipv4": { + "activate": true, + "prefix_list_in": "PL_In_Test_1", + "prefix_list_out": "PL_Out_Test_1" + }, + "address_family_ipv6": { + "activate": false + }, + "default_originate": { + "enabled": true, + "always": true + }, + "update_source": "lo0", + "bfd": false, + "ebgp_multihop": 3, + "route_map_out": "TEST_OUT", + "route_map_in": "TEST_IN", + "local_as": 777 + }, + { + "name": "Tenant_C_BGP_PEER_GROUP2", + "remote_as": "667", + "description": "Tenant C peer group2", + "update_source": "lo0", + "address_family_ipv4": { + "activate": true, + "route_map_in": "TEST_IN", + "route_map_out": "TEST_OUT" + } + } + ], + "vrfs": [ + { + "name": "Tenant_C_OP_Zone", + "vrf_vni": 30, + "enable_mlag_ibgp_peering_vrfs": true, + "mlag_ibgp_peering_vlan": 2, + "svis": [ + { + "id": 310, + "name": "Tenant_C_OP_Zone_1", + "tags": [ + "opzone" + ], + "enabled": true, + "ip_address_virtual": "10.3.10.1/24" + }, + { + "id": 311, + "name": "Tenant_C_OP_Zone_2", + "tags": [ + "opzone" + ], + "enabled": true, + "ip_address_virtual": "10.3.11.1/24" + } + ] + }, + { + "name": "Tenant_C_WAN_Zone", + "vrf_vni": 31, + "svis": [ + { + "id": 350, + "name": "Tenant_C_WAN_Zone_1", + "tags": [ + "wan" + ], + "enabled": true, + "ip_address_virtual": "10.3.50.1/24" + } + ], + "bgp_peer_groups": [ + { + "name": "Tenant_C_WAN_Zone_BGP_PEER_GROUP", + "remote_as": "666", + "description": "Tenant C VRF WAN Zone peer group", + "send_community": "all", + "next_hop_self": true, + "maximum_routes": 1000, + "default_originate": { + "enabled": true, + "always": true + }, + "address_family_ipv4": { + "activate": true + }, + "address_family_ipv6": { + "activate": true + }, + "nodes": [ + "DC1-BL2B" + ], + "update_source": "lo0", + "bfd": false, + "ebgp_multihop": 3, + "route_map_out": "TEST_OUT", + "route_map_in": "TEST_IN", + "local_as": 777 + } + ], + "bgp_peers": [ + { + "ip_address": "1.1.1.1", + "peer_group": "Tenant_C_WAN_Zone_BGP_PEER_GROUP", + "description": "test_description", + "nodes": [ + "DC1-BL2B" + ], + "set_ipv4_next_hop": "1.1.1.1" + }, + { + "ip_address": "BEBA::C0CA:C07A", + "peer_group": "Tenant_C_WAN_Zone_BGP_PEER_GROUP", + "nodes": [ + "DC1-BL2B" + ], + "description": "test_ipv6" + }, + { + "ip_address": "2.2.2.2", + "peer_group": "Tenant_C_BGP_PEER_GROUP", + "nodes": [ + "DC1-BL2A" + ], + "description": "test_bgp_peer_group_without_nodes" + }, + { + "ip_address": "2.2.2.3", + "peer_group": "Tenant_C_BGP_PEER_GROUP2", + "nodes": [ + "DC1-BL2A" + ], + "description": "test_bgp_peer_group_without_nodes_2nd_time" + }, + { + "ip_address": "2.2.2.3", + "peer_group": "Tenant_C_WAN_Zone_BGP_PEER_GROUP", + "nodes": [ + "DC1-BL2B" + ], + "description": "test_duplicate_peer_ip_address" + } + ] + } + ] + } + ], + "tenant_d": [ + { + "name": "Tenant_D", + "mac_vrf_vni_base": 40000, + "vrfs": [ + { + "name": "Tenant_D_OP_Zone", + "vrf_vni": 40, + "enable_mlag_ibgp_peering_vrfs": true, + "mlag_ibgp_peering_vlan": 2, + "svis": [ + { + "id": 410, + "name": "Tenant_D_v6_OP_Zone_1", + "tags": [ + "v6opzone" + ], + "enabled": true, + "ip_address_virtual": "10.3.10.1/24", + "ipv6_address_virtuals": [ + "2001:db8:310::1/64", + "2001:db8:311::1/64", + "2001:db8:312::1/64" + ] + }, + { + "id": 411, + "name": "Tenant_D_v6_OP_Zone_2", + "tags": [ + "v6opzone" + ], + "enabled": true, + "ip_virtual_router_addresses": [ + "10.3.11.1/24" + ], + "ipv6_virtual_router_addresses": [ + "2001:db8:311::1" + ], + "nodes": [ + { + "node": "DC1-LEAF2A", + "ip_address": "10.3.11.2/24", + "ipv6_address": "2001:db8:311::2/64" + }, + { + "node": "DC1-LEAF2B", + "ip_address": "10.3.11.3/24", + "ipv6_address": "2001:db8:311::3/64" + }, + { + "node": "evpn_services_l2_only_false", + "ip_address": "10.3.11.4/24", + "ipv6_address": "2001:db8:311::4/64" + } + ] + }, + { + "id": 412, + "name": "Tenant_D_v6_OP_Zone_1", + "tags": [ + "v6opzone" + ], + "enabled": true, + "profile": "GENERIC_DUAL_STACK" + }, + { + "id": 413, + "name": "Tenant_D_v6_OP_Zone_3", + "tags": [ + "v6opzone" + ], + "enabled": true, + "profile": "TEST_SVI_NODE_INHERIT", + "ip_virtual_router_addresses": [ + "11.4.13.1" + ], + "ipv6_virtual_router_addresses": [ + "2001:db9:413::1" + ], + "nodes": [ + { + "node": "DC1-LEAF2A", + "ip_address": "11.4.13.2/24", + "ipv6_address": "2001:db9:413::2/64" + }, + { + "node": "DC1-LEAF2B", + "ip_address": "101.4.13.2/24", + "ipv6_address": "2002:db9:413::2/64", + "ip_virtual_router_addresses": [ + "101.4.13.1" + ], + "ipv6_virtual_router_addresses": [ + "2002:db9:413::1" + ] + }, + { + "node": "evpn_services_l2_only_false", + "ip_helpers": [ + { + "ip_helper": "1.1.1.2", + "source_interface": "lo102", + "source_vrf": "TEST" + } + ] + } + ] + } + ], + "static_routes": [ + { + "destination_address_prefix": "0.0.0.0/0", + "gateway": "10.3.11.4", + "nodes": [ + "DC1-LEAF2A", + "DC1-LEAF2B" + ] + }, + { + "destination_address_prefix": "1.1.1.0/24", + "gateway": "10.3.11.4", + "nodes": [ + "DC1-LEAF2A", + "DC1-LEAF2B" + ], + "track_bfd": true, + "name": "Track-bfd-network-services" + } + ], + "ipv6_static_routes": [ + { + "destination_address_prefix": "::/0", + "gateway": "2001:db8:311::4", + "name": "IPv6-test-2", + "nodes": [ + "DC1-LEAF2A", + "DC1-LEAF2B" + ] + }, + { + "destination_address_prefix": "2001:db8::/32", + "gateway": "2001:db8:310::1", + "name": "IPv6-test", + "nodes": [ + "DC1-LEAF1A" + ] + }, + { + "destination_address_prefix": "2001:db9::/32", + "gateway": "2001:db8:310::1", + "name": "IPv6-test-1", + "nodes": [ + "DC1-LEAF1A" + ] + }, + { + "destination_address_prefix": "2001:dba::/32", + "gateway": "2001:db8:310::1", + "name": "Track-bfd-network-services", + "track_bfd": true, + "nodes": [ + "DC1-LEAF2A" + ] + } + ] + }, + { + "name": 12345678, + "vrf_vni": 41, + "svis": [ + { + "id": 450, + "name": "Tenant_D_v6_WAN_Zone_1", + "tags": [ + "v6wan" + ], + "enabled": true, + "ipv6_address_virtuals": [ + "2001:db8:355::1/64" + ] + }, + { + "id": 451, + "name": "Tenant_D_v6_WAN_Zone_2", + "tags": [ + "v6wan" + ], + "enabled": true, + "profile": "GENERIC_FULL_V6" + }, + { + "id": 452, + "name": "Tenant_D_v6_WAN_Zone_3", + "tags": [ + "v6wan" + ], + "enabled": true, + "profile": "GENERIC_DUAL_STACK" + } + ] + }, + { + "name": "default", + "vrf_id": 123, + "ospf": { + "enabled": true, + "process_id": 123 + }, + "svis": [ + { + "id": 1234, + "name": "VRF_DEFAULT_SVI_WITH_OSPF", + "ospf": { + "area": "0.0.0.0", + "enabled": true + } + } + ] + } + ] + } + ], + "svi_profiles": [ + { + "profile": "GENERIC", + "mtu": 1560, + "enabled": true + }, + { + "profile": "GENERIC_FULL", + "name": "GENERIC Name", + "mtu": 1560, + "enabled": false, + "ip_address_virtual": "10.1.10.254/24" + }, + { + "profile": "GENERIC_FULL_V6", + "name": "GENERIC Name V6", + "mtu": 1560, + "enabled": false, + "ipv6_address_virtuals": [ + "2001:db8:451::1/64" + ] + }, + { + "profile": "GENERIC_DUAL_STACK", + "name": "GENERIC DUAL STACK v4 and v6", + "mtu": 1560, + "enabled": false, + "ip_address_virtual": "10.4.12.254/24", + "ipv6_address_virtuals": [ + "2001:db8:412::1/64" + ], + "ipv6_enable": false + }, + { + "profile": "TEST_SVI_NODE_INHERIT", + "name": "Test the SVI and node config inheritance", + "mtu": 1560, + "enabled": false, + "ip_address_virtual": "10.4.13.254/24", + "ipv6_address_virtuals": [ + "2001:db8:413::1/64" + ], + "ip_helpers": [ + { + "ip_helper": "1.1.1.1", + "source_interface": "lo101", + "source_vrf": "TEST" + } + ], + "nodes": [ + { + "node": "evpn_services_l2_only_false", + "ip_address": "12.4.13.2/24", + "ipv6_address": "2012:db9:413::2/64", + "ip_virtual_router_addresses": [ + "12.4.13.1" + ], + "ipv6_virtual_router_addresses": [ + "2012:db9:413::1" + ] + } + ] + }, + { + "profile": "GENERIC_DHCP", + "mtu": 1560, + "enabled": false, + "ip_helpers": [ + { + "ip_helper": "2.2.2.2", + "source_interface": "lo101", + "source_vrf": "MGMT" + } + ] + }, + { + "profile": "WITH_NO_MTU", + "enabled": true + }, + { + "profile": "WITH_DHCP_AND_SNOOPING", + "enabled": true, + "ip_address_virtual": "10.1.11.254/24", + "igmp_snooping_enabled": false, + "ip_helpers": [ + { + "ip_helper": "1.1.1.1", + "source_interface": "lo100", + "source_vrf": "TEST" + } + ] + }, + { + "profile": "WITH_DHCP", + "enabled": true, + "ip_helpers": [ + { + "ip_helper": "1.1.1.1", + "source_interface": "lo100", + "source_vrf": "MGMT" + } + ] + }, + { + "profile": "DERIVED_DHCP", + "parent_profile": "GENERIC_DHCP", + "enabled": true + } + ], + "network_services_keys": [ + { + "name": "tenant_a" + }, + { + "name": "tenant_b" + }, + { + "name": "tenant_c" + }, + { + "name": "tenant_d" + } + ], + "type": "l3leaf", + "my_dci_ethernet_interfaces": [ + { + "name": "Ethernet4000", + "description": "My test", + "ip_address": "10.1.2.3/12", + "shutdown": false, + "switchport": { + "enabled": false + }, + "mtu": 1500, + "peer": "MY-own-peer", + "peer_interface": "Ethernet123", + "peer_type": "my_precious" + } + ], + "override_ntp": null, + "evpn_overlay_bgp_rtc": true, + "my_special_dci_ethernet_interfaces": [ + { + "name": "Ethernet4000", + "ip_address": "10.3.2.1/21" + } + ], + "overlay_rd_type": { + "admin_subfield": "vtep_loopback" + }, + "overlay_rt_type": { + "admin_subfield": "bgp_as" + }, + "inventory_file": "/home/holbech/avd/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/hosts.yml", + "inventory_dir": "/home/holbech/avd/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory", + "ansible_host": "192.168.200.110", + "inventory_hostname": "DC1-BL1A", + "inventory_hostname_short": "DC1-BL1A", + "group_names": [ + "AVD_LAB", + "DC1_BL1", + "DC1_FABRIC", + "DC1_LEAFS", + "DC1_SERVERS", + "DC1_TENANTS_NETWORKS", + "EOS_DESIGNS_UNIT_TESTS" + ], + "custom_structured_configuration_list_merge": "append", + "override_ip_name_servers": [ + { + "ip_address": "1.1.1.1", + "vrf": "MGMT" + } + ], + "router_id_loopback_description": "MY_ROUTER_ID_LOOPBACK", + "vtep_vvtep_ip": "192.168.255.255/32", + "event_handlers": [ + { + "name": "evpn-blacklist-recovery", + "actions": { + "bash_command": "FastCli -p 15 -c \"clear bgp evpn host-flap\"" + }, + "delay": 300, + "trigger": "on-logging", + "trigger_on_logging": { + "regex": "EVPN-3-BLACKLISTED_DUPLICATE_MAC" + }, + "asynchronous": true + } + ], + "template_timezone": "correctly_templated_timezone", + "timezone": "correctly_templated_timezone", + "mac_address_table": { + "aging_time": 42 + }, + "my_mac_address_table": { + "notification_host_flap": { + "logging": true + } + }, + "override_mac_address_table": { + "notification_host_flap": { + "logging": true + } + }, + "generate_cv_tags": { + "topology_hints": true + }, + "ansible_facts": {}, + "testdir": "eos_designs_unit_tests", + "playbook_dir": "/home/holbech/avd/python-avd/scripts", + "ansible_playbook_python": "/usr/bin/python3.10", + "ansible_config_file": null, + "groups": { + "all": [ + "always-configure-ip-routing", + "bgp-options", + "connected_endpoints", + "cvp-instance-ips-cvaas", + "cvp-instance-ips-onprem-token", + "device.with.dots.in.hostname", + "evpn-vtep-with-default-vrf-not-evpn", + "duplicate-vrfs", + "filter.only_vlans_in_use", + "filter.vrfs", + "generate-cv-tags-1", + "generate-cv-tags-2", + "ignore-custom-keys-in-data-models", + "isis-system-id-format-using-underlay-loopback", + "isis-system-id-format-using-node-id", + "no_mgmt_interface", + "no_mgmt_gateway", + "ntp-settings-1", + "ntp-settings-2", + "hardware_counters", + "source-interfaces", + "mgmt_interface_description", + "mgmt_interface_ipv6", + "mgmt_interface_dualstack", + "default_overlay_protocol_cvx", + "default_overlay_protocol_her", + "evpn_vlan_bundle", + "evpn_vlan_bundle_svi_l2vlan", + "default_interface_mtu_hostvars", + "default_interface_mtu_platform", + "evpn-to-ipvpn-gateway", + "vrfs_rd_rt_override", + "spanning-tree-mode-rapid-pvst", + "node-type-l3-interfaces", + "ipv4-acls", + "only-connected-endpoints", + "platform_settings", + "varpv6", + "override_uplink_type-d", + "override_uplink_type-u", + "core-1-isis-sr-ldp", + "core-2-ospf-ldp", + "core-3-isis-sr-ldp", + "core-4-multicast", + "network-ports-tests.1", + "network-ports-tests-2", + "P2P-UPLINKS-IPV4-PREFIX-LENGTH", + "bgp-peer-groups-1", + "bgp-peer-groups-2", + "bgp-peer-groups-3", + "bgp-from-network-services-1", + "bgp-from-network-services-2", + "SVI_PROFILE_NODE_1", + "SVI_PROFILE_NODE_2", + "RD-RT-ADMIN-SUBFIELD-L3LEAF1", + "RD-RT-ADMIN-SUBFIELD-L3LEAF2", + "RD-RT-ADMIN-SUBFIELD-L3LEAF3", + "RD-RT-ADMIN-SUBFIELD-L3LEAF4", + "RD-RT-ADMIN-SUBFIELD-L3LEAF5", + "RD-RT-ADMIN-SUBFIELD-L3LEAF6", + "RD-RT-ADMIN-SUBFIELD-L3LEAF7", + "AUTO_BGP_ASN_LEAF1A", + "AUTO_BGP_ASN_LEAF1B", + "AUTO_BGP_ASN_LEAF2", + "AUTO_BGP_ASN_LEAF3A", + "AUTO_BGP_ASN_LEAF3B", + "AUTO_BGP_ASN_LEAF4A", + "AUTO_BGP_ASN_LEAF4B", + "AUTO_BGP_ASN_LEAF5A", + "AUTO_BGP_UNGROUPED_LEAF6", + "AUTO_BGP_ASN_LEAF7A", + "AUTO_BGP_ASN_LEAF7B", + "AUTO_BGP_ASN_LEAF8A", + "AUTO_BGP_ASN_LEAF8B", + "AUTO_NODE_TYPE_SPINE01", + "AUTO_NODE_TYPE_SPINE02", + "AUTO_NODE_TYPE_LEAF01", + "AUTO_NODE_TYPE_UNGROUPED_LEAF02", + "OVERLAY_ROUTING_PROTOCOL_HER_L3LEAF1", + "OVERLAY_ROUTING_PROTOCOL_HER_L3LEAF2", + "OVERLAY_ROUTING_PROTOCOL_HER_L3LEAF3A", + "OVERLAY_ROUTING_PROTOCOL_HER_L3LEAF3B", + "OVERLAY_ROUTING_PROTOCOL_CVX_L3LEAF1", + "OVERLAY_ROUTING_PROTOCOL_CVX_L3LEAF2", + "OVERLAY_ROUTING_PROTOCOL_CVX_SERVER1", + "OVERLAY_ROUTING_PROTOCOL_CVX_SERVER2", + "UNDERLAY_FILTER_PEER_AS_L3LEAF1", + "UNDERLAY_FILTER_PEER_AS_SPINE1", + "UNDERLAY_FILTER_PEER_AS_SPINE2", + "SNMP_SYSTEM_MAC_ENGINEID_1", + "SNMP_SYSTEM_MAC_ENGINEID_2", + "SNMP_AUTOGEN_ENGINEID", + "snmp-settings-1", + "snmp-settings-2", + "underlay_filter_peer_as_evpn_1", + "underlay_filter_peer_as_evpn_2", + "underlay_filter_peer_as_evpn_3", + "l3_edge_bgp", + "l3_edge_ospf", + "l3_edge_isis", + "l3_edge_multicast", + "uplink-native-vlan-grandparent", + "uplink-native-vlan-parent", + "uplink-native-vlan-child", + "inband-mgmt-parent", + "inband-mgmt-parent-vrf", + "inband-mgmt-subnet", + "inband-mgmt-subnet-vrf", + "inband-mgmt-ip", + "inband-mgmt-parent-dualstack1", + "inband-mgmt-parent-dualstack2", + "inband-mgmt-dualstack-subnets", + "inband-mgmt-dualstack-ips", + "inband-mgmt-parent-ipv6-1", + "inband-mgmt-parent-ipv6-2", + "inband-mgmt-ipv6-only", + "inband-mgmt-ipv6-only-vrf", + "inband-mgmt-mlag-a", + "inband-mgmt-mlag-b", + "TEST-MGMT-GATEWAY-IN-NODE-GROUP", + "UPLINK_P2P_VRFS_TESTS_SPINE1", + "UPLINK_P2P_VRFS_TESTS_SPINE2", + "UPLINK_P2P_VRFS_TESTS_LEAF1", + "UPLINK_P2P_VRFS_TESTS_L2LEAF1", + "uplink_lan_l2leaf", + "uplink_lan_wan_router1", + "uplink_lan_wan_router2", + "downlink-pools-spine1", + "downlink-pools-spine2", + "downlink-pools-l3leaf1", + "downlink-pools-l3leaf2", + "downlink-pools-l3leaf3", + "downlink-pools-l3leaf4", + "SL-LEAF0A", + "SL-LEAF0B", + "SL-LEAF1A", + "SL-LEAF1B", + "SL-MLEAF1", + "SL-LEAF2A", + "SL-LEAF2B", + "DUP-LEAF1", + "DUP-LEAF2", + "7010TX-LEAF1", + "7010TX-LEAF2", + "IGMP-QUERIER-L3LEAF1A", + "IGMP-QUERIER-L2LEAF1A", + "UNDERLAY-MULTICAST-SPINE1", + "UNDERLAY-MULTICAST-SPINE2", + "UNDERLAY-MULTICAST-L2LEAF1A", + "EVPN-MULTICAST-SPINE1", + "EVPN-MULTICAST-L2LEAF1A", + "CUSTOM-TEMPLATES-SPINE1", + "CUSTOM-TEMPLATES-L3LEAF1A", + "CUSTOM-TEMPLATES-L3LEAF1B", + "CUSTOM-TEMPLATES-L2LEAF1A", + "CUSTOM-TEMPLATES-L2LEAF1B", + "legacy-autovpn-rr1", + "legacy-autovpn-rr2", + "legacy-autovpn-edge", + "legacy-autovpn-edge-no-default-policy", + "cv-pathfinder-edge-no-default-policy", + "cv-pathfinder-edge-custom-default-policy", + "OVERRIDE_VTEP_L3LEAF1A", + "OVERRIDE_VTEP_L3LEAF1B", + "MLAG_ODD_ID_L3LEAF1A", + "MLAG_ODD_ID_L3LEAF1B", + "MLAG_IPV6_L3LEAF1A", + "MLAG_IPV6_L3LEAF1B", + "MLAG_SAME_SUBNET_L3LEAF1A", + "MLAG_SAME_SUBNET_L3LEAF1B", + "MLAG_SAME_SUBNET_L3LEAF2A", + "MLAG_SAME_SUBNET_L3LEAF2B", + "ptp-tests-spine1", + "ptp-tests-spine2", + "ptp-tests-spine3", + "ptp-tests-leaf1", + "ptp-tests-leaf2", + "ptp-tests-l2leaf1-ptp-disabled", + "ptp-tests-l2leaf2-ptp-enabled", + "ptp-tests-l2leaf2-ptp-enabled-uplink-disabled", + "UPLINK-MLAG-STRUCTURED-CONFIG-SPINE1", + "UPLINK-MLAG-STRUCTURED-CONFIG-L3LEAF1A", + "UPLINK-MLAG-STRUCTURED-CONFIG-L3LEAF1B", + "UPLINK-MLAG-STRUCTURED-CONFIG-L2LEAF1A", + "UPLINK-MLAG-STRUCTURED-CONFIG-L2LEAF1B", + "sflow-tests-spine1", + "sflow-tests-spine2", + "sflow-tests-leaf1", + "sflow-tests-leaf2", + "sflow-tests-l2-leaf1", + "sflow-tests-l2-leaf2", + "trunk-group-tests-l3leaf1a", + "trunk-group-tests-l3leaf1b", + "trunk-group-tests-l3leaf2a", + "trunk-group-tests-l3leaf2b", + "trunk-group-tests-l2leaf1a", + "trunk-group-tests-l2leaf1b", + "trunk-group-tests-l2leaf3", + "trunk-group-tests-l2leaf4", + "flow-tracking-tests-leaf1", + "flow-tracking-tests-l2-leaf1", + "flow-tracking-tests-l2-leaf2", + "CUSTOM-PYTHON_MODULES-SPINE1", + "CUSTOM-PYTHON_MODULES-L3LEAF1A", + "CUSTOM-PYTHON_MODULES-L3LEAF1B", + "CUSTOM-PYTHON_MODULES-L3LEAF2", + "MH-L2LEAF1A", + "UNDERLAY-MULTICAST-L3LEAF1A", + "UNDERLAY-MULTICAST-L3LEAF1B", + "UNDERLAY-MULTICAST-L3LEAF2A", + "UNDERLAY-MULTICAST-L3LEAF2B", + "cv-pathfinder-edge2A", + "cv-pathfinder-edge2B", + "site-ha-enabled-leaf2A", + "site-ha-enabled-leaf2B", + "cv-pathfinder-transit1A", + "cv-pathfinder-transit1B", + "site-ha-enabled-leaf1", + "cv-pathfinder-edge3A", + "cv-pathfinder-edge3B", + "cv-pathfinder-edge4A", + "cv-pathfinder-edge4B", + "cv-pathfinder-edge", + "cv-pathfinder-edge1", + "site-ha-disabled-leaf", + "cv-pathfinder-pathfinder", + "sflow-tests-leaf3", + "sflow-tests-leaf4", + "flow-tracking-tests-spine1", + "flow-tracking-tests-spine2", + "EVPN-MULTICAST-L3LEAF1A", + "EVPN-MULTICAST-L3LEAF1B", + "EVPN-MULTICAST-L3LEAF2A", + "EVPN-MULTICAST-L3LEAF3A", + "EVPN-MULTICAST-L3LEAF3B", + "EVPN-MULTICAST-DISABLED", + "DC1-SPINE1", + "DC1-SPINE2", + "DC1-SPINE3", + "DC1-SPINE4", + "flow-tracking-tests-leaf2", + "flow-tracking-tests-leaf4", + "DC1-LEAF1A", + "DC1-LEAF2A", + "DC1-LEAF2B", + "DC1-SVC3A", + "DC1-SVC3B", + "DC1-BL1A", + "DC1-BL1B", + "DC1-BL2A", + "DC1-BL2B", + "DC1-CL1A", + "DC1-CL1B", + "evpn_services_l2_only_true", + "evpn_services_l2_only_false", + "DC1_UNDEPLOYED_LEAF1A", + "DC1_UNDEPLOYED_LEAF1B", + "DC1-L2LEAF1A", + "DC1-L2LEAF1B", + "DC1-L2LEAF2A", + "DC1-L2LEAF2B", + "DC1-L2LEAF3A", + "DC1-L2LEAF4A", + "DC1.L2LEAF5A", + "DC1.L2LEAF5B", + "DC1.L2LEAF6A", + "DC1.L2LEAF6B", + "mgmt_interface_default", + "mgmt_interface_fabric", + "mgmt_interface_host", + "mgmt_interface_platform", + "cv-pathfinder-pathfinder1", + "cv-pathfinder-pathfinder2", + "cv-pathfinder-custom-control-plane-policy-edge-1", + "cv-pathfinder-custom-control-plane-policy-pathfinder-1", + "cv-pathfinder-custom-control-plane-policy-edge-2", + "cv-pathfinder-custom-control-plane-policy-edge-3", + "flow-tracking-tests-leaf3", + "MLAG-OSPF-L3LEAF1A", + "MLAG-OSPF-L3LEAF1B", + "MH-LEAF1A", + "MH-LEAF1B", + "MH-LEAF2A" + ], + "ungrouped": [], + "EOS_DESIGNS_UNIT_TESTS": [ + "always-configure-ip-routing", + "bgp-options", + "connected_endpoints", + "cvp-instance-ips-cvaas", + "cvp-instance-ips-onprem-token", + "device.with.dots.in.hostname", + "evpn-vtep-with-default-vrf-not-evpn", + "duplicate-vrfs", + "filter.only_vlans_in_use", + "filter.vrfs", + "generate-cv-tags-1", + "generate-cv-tags-2", + "ignore-custom-keys-in-data-models", + "isis-system-id-format-using-underlay-loopback", + "isis-system-id-format-using-node-id", + "no_mgmt_interface", + "no_mgmt_gateway", + "ntp-settings-1", + "ntp-settings-2", + "hardware_counters", + "source-interfaces", + "mgmt_interface_description", + "mgmt_interface_ipv6", + "mgmt_interface_dualstack", + "default_overlay_protocol_cvx", + "default_overlay_protocol_her", + "evpn_vlan_bundle", + "evpn_vlan_bundle_svi_l2vlan", + "default_interface_mtu_hostvars", + "default_interface_mtu_platform", + "evpn-to-ipvpn-gateway", + "vrfs_rd_rt_override", + "spanning-tree-mode-rapid-pvst", + "node-type-l3-interfaces", + "ipv4-acls", + "only-connected-endpoints", + "platform_settings", + "varpv6", + "override_uplink_type-d", + "override_uplink_type-u", + "core-1-isis-sr-ldp", + "core-2-ospf-ldp", + "core-3-isis-sr-ldp", + "core-4-multicast", + "network-ports-tests.1", + "network-ports-tests-2", + "P2P-UPLINKS-IPV4-PREFIX-LENGTH", + "bgp-peer-groups-1", + "bgp-peer-groups-2", + "bgp-peer-groups-3", + "bgp-from-network-services-1", + "bgp-from-network-services-2", + "SVI_PROFILE_NODE_1", + "SVI_PROFILE_NODE_2", + "RD-RT-ADMIN-SUBFIELD-L3LEAF1", + "RD-RT-ADMIN-SUBFIELD-L3LEAF2", + "RD-RT-ADMIN-SUBFIELD-L3LEAF3", + "RD-RT-ADMIN-SUBFIELD-L3LEAF4", + "RD-RT-ADMIN-SUBFIELD-L3LEAF5", + "RD-RT-ADMIN-SUBFIELD-L3LEAF6", + "RD-RT-ADMIN-SUBFIELD-L3LEAF7", + "AUTO_BGP_ASN_LEAF1A", + "AUTO_BGP_ASN_LEAF1B", + "AUTO_BGP_ASN_LEAF2", + "AUTO_BGP_ASN_LEAF3A", + "AUTO_BGP_ASN_LEAF3B", + "AUTO_BGP_ASN_LEAF4A", + "AUTO_BGP_ASN_LEAF4B", + "AUTO_BGP_ASN_LEAF5A", + "AUTO_BGP_UNGROUPED_LEAF6", + "AUTO_BGP_ASN_LEAF7A", + "AUTO_BGP_ASN_LEAF7B", + "AUTO_BGP_ASN_LEAF8A", + "AUTO_BGP_ASN_LEAF8B", + "AUTO_NODE_TYPE_SPINE01", + "AUTO_NODE_TYPE_SPINE02", + "AUTO_NODE_TYPE_LEAF01", + "AUTO_NODE_TYPE_UNGROUPED_LEAF02", + "OVERLAY_ROUTING_PROTOCOL_HER_L3LEAF1", + "OVERLAY_ROUTING_PROTOCOL_HER_L3LEAF2", + "OVERLAY_ROUTING_PROTOCOL_HER_L3LEAF3A", + "OVERLAY_ROUTING_PROTOCOL_HER_L3LEAF3B", + "OVERLAY_ROUTING_PROTOCOL_CVX_L3LEAF1", + "OVERLAY_ROUTING_PROTOCOL_CVX_L3LEAF2", + "OVERLAY_ROUTING_PROTOCOL_CVX_SERVER1", + "OVERLAY_ROUTING_PROTOCOL_CVX_SERVER2", + "UNDERLAY_FILTER_PEER_AS_L3LEAF1", + "UNDERLAY_FILTER_PEER_AS_SPINE1", + "UNDERLAY_FILTER_PEER_AS_SPINE2", + "SNMP_SYSTEM_MAC_ENGINEID_1", + "SNMP_SYSTEM_MAC_ENGINEID_2", + "SNMP_AUTOGEN_ENGINEID", + "snmp-settings-1", + "snmp-settings-2", + "underlay_filter_peer_as_evpn_1", + "underlay_filter_peer_as_evpn_2", + "underlay_filter_peer_as_evpn_3", + "l3_edge_bgp", + "l3_edge_ospf", + "l3_edge_isis", + "l3_edge_multicast", + "uplink-native-vlan-grandparent", + "uplink-native-vlan-parent", + "uplink-native-vlan-child", + "inband-mgmt-parent", + "inband-mgmt-parent-vrf", + "inband-mgmt-subnet", + "inband-mgmt-subnet-vrf", + "inband-mgmt-ip", + "inband-mgmt-parent-dualstack1", + "inband-mgmt-parent-dualstack2", + "inband-mgmt-dualstack-subnets", + "inband-mgmt-dualstack-ips", + "inband-mgmt-parent-ipv6-1", + "inband-mgmt-parent-ipv6-2", + "inband-mgmt-ipv6-only", + "inband-mgmt-ipv6-only-vrf", + "inband-mgmt-mlag-a", + "inband-mgmt-mlag-b", + "TEST-MGMT-GATEWAY-IN-NODE-GROUP", + "UPLINK_P2P_VRFS_TESTS_SPINE1", + "UPLINK_P2P_VRFS_TESTS_SPINE2", + "UPLINK_P2P_VRFS_TESTS_LEAF1", + "UPLINK_P2P_VRFS_TESTS_L2LEAF1", + "uplink_lan_l2leaf", + "uplink_lan_wan_router1", + "uplink_lan_wan_router2", + "downlink-pools-spine1", + "downlink-pools-spine2", + "downlink-pools-l3leaf1", + "downlink-pools-l3leaf2", + "downlink-pools-l3leaf3", + "downlink-pools-l3leaf4", + "SL-LEAF0A", + "SL-LEAF0B", + "SL-LEAF1A", + "SL-LEAF1B", + "SL-MLEAF1", + "SL-LEAF2A", + "SL-LEAF2B", + "DUP-LEAF1", + "DUP-LEAF2", + "7010TX-LEAF1", + "7010TX-LEAF2", + "IGMP-QUERIER-L3LEAF1A", + "IGMP-QUERIER-L2LEAF1A", + "UNDERLAY-MULTICAST-SPINE1", + "UNDERLAY-MULTICAST-SPINE2", + "UNDERLAY-MULTICAST-L2LEAF1A", + "EVPN-MULTICAST-SPINE1", + "EVPN-MULTICAST-L2LEAF1A", + "CUSTOM-TEMPLATES-SPINE1", + "CUSTOM-TEMPLATES-L3LEAF1A", + "CUSTOM-TEMPLATES-L3LEAF1B", + "CUSTOM-TEMPLATES-L2LEAF1A", + "CUSTOM-TEMPLATES-L2LEAF1B", + "legacy-autovpn-rr1", + "legacy-autovpn-rr2", + "legacy-autovpn-edge", + "legacy-autovpn-edge-no-default-policy", + "cv-pathfinder-edge-no-default-policy", + "cv-pathfinder-edge-custom-default-policy", + "OVERRIDE_VTEP_L3LEAF1A", + "OVERRIDE_VTEP_L3LEAF1B", + "MLAG_ODD_ID_L3LEAF1A", + "MLAG_ODD_ID_L3LEAF1B", + "MLAG_IPV6_L3LEAF1A", + "MLAG_IPV6_L3LEAF1B", + "MLAG_SAME_SUBNET_L3LEAF1A", + "MLAG_SAME_SUBNET_L3LEAF1B", + "MLAG_SAME_SUBNET_L3LEAF2A", + "MLAG_SAME_SUBNET_L3LEAF2B", + "ptp-tests-spine1", + "ptp-tests-spine2", + "ptp-tests-spine3", + "ptp-tests-leaf1", + "ptp-tests-leaf2", + "ptp-tests-l2leaf1-ptp-disabled", + "ptp-tests-l2leaf2-ptp-enabled", + "ptp-tests-l2leaf2-ptp-enabled-uplink-disabled", + "UPLINK-MLAG-STRUCTURED-CONFIG-SPINE1", + "UPLINK-MLAG-STRUCTURED-CONFIG-L3LEAF1A", + "UPLINK-MLAG-STRUCTURED-CONFIG-L3LEAF1B", + "UPLINK-MLAG-STRUCTURED-CONFIG-L2LEAF1A", + "UPLINK-MLAG-STRUCTURED-CONFIG-L2LEAF1B", + "sflow-tests-spine1", + "sflow-tests-spine2", + "sflow-tests-leaf1", + "sflow-tests-leaf2", + "sflow-tests-l2-leaf1", + "sflow-tests-l2-leaf2", + "trunk-group-tests-l3leaf1a", + "trunk-group-tests-l3leaf1b", + "trunk-group-tests-l3leaf2a", + "trunk-group-tests-l3leaf2b", + "trunk-group-tests-l2leaf1a", + "trunk-group-tests-l2leaf1b", + "trunk-group-tests-l2leaf3", + "trunk-group-tests-l2leaf4", + "flow-tracking-tests-leaf1", + "flow-tracking-tests-l2-leaf1", + "flow-tracking-tests-l2-leaf2", + "CUSTOM-PYTHON_MODULES-SPINE1", + "CUSTOM-PYTHON_MODULES-L3LEAF1A", + "CUSTOM-PYTHON_MODULES-L3LEAF1B", + "CUSTOM-PYTHON_MODULES-L3LEAF2", + "MH-L2LEAF1A", + "cv-pathfinder-edge2A", + "cv-pathfinder-edge2B", + "site-ha-enabled-leaf2A", + "site-ha-enabled-leaf2B", + "cv-pathfinder-transit1A", + "cv-pathfinder-transit1B", + "site-ha-enabled-leaf1", + "cv-pathfinder-edge3A", + "cv-pathfinder-edge3B", + "cv-pathfinder-edge4A", + "cv-pathfinder-edge4B", + "cv-pathfinder-edge", + "cv-pathfinder-edge1", + "site-ha-disabled-leaf", + "cv-pathfinder-pathfinder", + "flow-tracking-tests-spine1", + "flow-tracking-tests-spine2", + "EVPN-MULTICAST-L3LEAF1A", + "EVPN-MULTICAST-L3LEAF1B", + "EVPN-MULTICAST-L3LEAF2A", + "EVPN-MULTICAST-L3LEAF3A", + "EVPN-MULTICAST-L3LEAF3B", + "EVPN-MULTICAST-DISABLED", + "flow-tracking-tests-leaf2", + "flow-tracking-tests-leaf4", + "UNDERLAY-MULTICAST-L3LEAF1A", + "UNDERLAY-MULTICAST-L3LEAF1B", + "UNDERLAY-MULTICAST-L3LEAF2A", + "UNDERLAY-MULTICAST-L3LEAF2B", + "sflow-tests-leaf3", + "sflow-tests-leaf4", + "DC1-SPINE1", + "DC1-SPINE2", + "DC1-SPINE3", + "DC1-SPINE4", + "DC1-LEAF1A", + "DC1-LEAF2A", + "DC1-LEAF2B", + "DC1-SVC3A", + "DC1-SVC3B", + "DC1-BL1A", + "DC1-BL1B", + "DC1-BL2A", + "DC1-BL2B", + "DC1-CL1A", + "DC1-CL1B", + "evpn_services_l2_only_true", + "evpn_services_l2_only_false", + "DC1_UNDEPLOYED_LEAF1A", + "DC1_UNDEPLOYED_LEAF1B", + "DC1-L2LEAF1A", + "DC1-L2LEAF1B", + "DC1-L2LEAF2A", + "DC1-L2LEAF2B", + "DC1-L2LEAF3A", + "DC1-L2LEAF4A", + "DC1.L2LEAF5A", + "DC1.L2LEAF5B", + "DC1.L2LEAF6A", + "DC1.L2LEAF6B", + "mgmt_interface_default", + "mgmt_interface_fabric", + "mgmt_interface_host", + "mgmt_interface_platform", + "cv-pathfinder-pathfinder1", + "cv-pathfinder-pathfinder2", + "cv-pathfinder-custom-control-plane-policy-edge-1", + "cv-pathfinder-custom-control-plane-policy-pathfinder-1", + "cv-pathfinder-custom-control-plane-policy-edge-2", + "cv-pathfinder-custom-control-plane-policy-edge-3", + "flow-tracking-tests-leaf3", + "MLAG-OSPF-L3LEAF1A", + "MLAG-OSPF-L3LEAF1B", + "MH-LEAF1A", + "MH-LEAF1B", + "MH-LEAF2A" + ], + "CLEAN_UNIT_TESTS": [ + "always-configure-ip-routing", + "bgp-options", + "connected_endpoints", + "cvp-instance-ips-cvaas", + "cvp-instance-ips-onprem-token", + "device.with.dots.in.hostname", + "evpn-vtep-with-default-vrf-not-evpn", + "duplicate-vrfs", + "filter.only_vlans_in_use", + "filter.vrfs", + "generate-cv-tags-1", + "generate-cv-tags-2", + "ignore-custom-keys-in-data-models", + "isis-system-id-format-using-underlay-loopback", + "isis-system-id-format-using-node-id", + "no_mgmt_interface", + "no_mgmt_gateway", + "ntp-settings-1", + "ntp-settings-2", + "hardware_counters", + "source-interfaces", + "mgmt_interface_description", + "mgmt_interface_ipv6", + "mgmt_interface_dualstack", + "default_overlay_protocol_cvx", + "default_overlay_protocol_her", + "evpn_vlan_bundle", + "evpn_vlan_bundle_svi_l2vlan", + "default_interface_mtu_hostvars", + "default_interface_mtu_platform", + "evpn-to-ipvpn-gateway", + "vrfs_rd_rt_override", + "spanning-tree-mode-rapid-pvst", + "node-type-l3-interfaces", + "ipv4-acls", + "only-connected-endpoints", + "platform_settings", + "varpv6" + ], + "OVERRIDE_UPLINK_TYPE": [ + "override_uplink_type-d", + "override_uplink_type-u" + ], + "CORE_UNIT_TESTS": [ + "core-1-isis-sr-ldp", + "core-2-ospf-ldp", + "core-3-isis-sr-ldp", + "core-4-multicast" + ], + "TRUNK_GROUP_TESTS": [ + "trunk-group-tests-l3leaf1a", + "trunk-group-tests-l3leaf1b", + "trunk-group-tests-l3leaf2a", + "trunk-group-tests-l3leaf2b", + "trunk-group-tests-l2leaf1a", + "trunk-group-tests-l2leaf1b", + "trunk-group-tests-l2leaf3", + "trunk-group-tests-l2leaf4" + ], + "TRUNK_GROUP_TESTS_L3LEAF": [ + "trunk-group-tests-l3leaf1a", + "trunk-group-tests-l3leaf1b", + "trunk-group-tests-l3leaf2a", + "trunk-group-tests-l3leaf2b" + ], + "TRUNK_GROUP_TESTS_L2LEAF": [ + "trunk-group-tests-l2leaf1a", + "trunk-group-tests-l2leaf1b", + "trunk-group-tests-l2leaf3", + "trunk-group-tests-l2leaf4" + ], + "NETWORK_PORTS_TESTS": [ + "network-ports-tests.1", + "network-ports-tests-2" + ], + "FABRIC_IP_ADDRESSING": [ + "P2P-UPLINKS-IPV4-PREFIX-LENGTH", + "MLAG_ODD_ID_L3LEAF1A", + "MLAG_ODD_ID_L3LEAF1B", + "MLAG_IPV6_L3LEAF1A", + "MLAG_IPV6_L3LEAF1B", + "MLAG_SAME_SUBNET_L3LEAF1A", + "MLAG_SAME_SUBNET_L3LEAF1B", + "MLAG_SAME_SUBNET_L3LEAF2A", + "MLAG_SAME_SUBNET_L3LEAF2B" + ], + "MLAG_ODD_ID": [ + "MLAG_ODD_ID_L3LEAF1A", + "MLAG_ODD_ID_L3LEAF1B" + ], + "MLAG_IPV6": [ + "MLAG_IPV6_L3LEAF1A", + "MLAG_IPV6_L3LEAF1B" + ], + "MLAG_SAME_SUBNET": [ + "MLAG_SAME_SUBNET_L3LEAF1A", + "MLAG_SAME_SUBNET_L3LEAF1B", + "MLAG_SAME_SUBNET_L3LEAF2A", + "MLAG_SAME_SUBNET_L3LEAF2B" + ], + "NODE_TYPE_OVERRIDES_TESTS": [ + "OVERRIDE_VTEP_L3LEAF1A", + "OVERRIDE_VTEP_L3LEAF1B" + ], + "OVERRIDE_VTEP_LEAFS": [ + "OVERRIDE_VTEP_L3LEAF1A", + "OVERRIDE_VTEP_L3LEAF1B" + ], + "UPLINK_MLAG_STRUCTURED_CONFIG_TESTS": [ + "UPLINK-MLAG-STRUCTURED-CONFIG-SPINE1", + "UPLINK-MLAG-STRUCTURED-CONFIG-L3LEAF1A", + "UPLINK-MLAG-STRUCTURED-CONFIG-L3LEAF1B", + "UPLINK-MLAG-STRUCTURED-CONFIG-L2LEAF1A", + "UPLINK-MLAG-STRUCTURED-CONFIG-L2LEAF1B" + ], + "UPLINK_MLAG_STRUCTURED_CONFIG_SPINES": [ + "UPLINK-MLAG-STRUCTURED-CONFIG-SPINE1" + ], + "UPLINK_MLAG_STRUCTURED_CONFIG_L3LEAFS": [ + "UPLINK-MLAG-STRUCTURED-CONFIG-L3LEAF1A", + "UPLINK-MLAG-STRUCTURED-CONFIG-L3LEAF1B" + ], + "UPLINK_MLAG_STRUCTURED_CONFIG_L2LEAFS": [ + "UPLINK-MLAG-STRUCTURED-CONFIG-L2LEAF1A", + "UPLINK-MLAG-STRUCTURED-CONFIG-L2LEAF1B" + ], + "UNDERLAY_MULTICAST_TESTS": [ + "UNDERLAY-MULTICAST-SPINE1", + "UNDERLAY-MULTICAST-SPINE2", + "UNDERLAY-MULTICAST-L2LEAF1A", + "UNDERLAY-MULTICAST-L3LEAF1A", + "UNDERLAY-MULTICAST-L3LEAF1B", + "UNDERLAY-MULTICAST-L3LEAF2A", + "UNDERLAY-MULTICAST-L3LEAF2B" + ], + "UNDERLAY_MULTICAST_SPINES": [ + "UNDERLAY-MULTICAST-SPINE1", + "UNDERLAY-MULTICAST-SPINE2" + ], + "UNDERLAY_MULTICAST_L3LEAFS": [ + "UNDERLAY-MULTICAST-L3LEAF1A", + "UNDERLAY-MULTICAST-L3LEAF1B", + "UNDERLAY-MULTICAST-L3LEAF2A", + "UNDERLAY-MULTICAST-L3LEAF2B" + ], + "UNDERLAY_MULTICAST_L3LEAF1": [ + "UNDERLAY-MULTICAST-L3LEAF1A", + "UNDERLAY-MULTICAST-L3LEAF1B" + ], + "UNDERLAY_MULTICAST_L3LEAF2": [ + "UNDERLAY-MULTICAST-L3LEAF2A", + "UNDERLAY-MULTICAST-L3LEAF2B" + ], + "UNDERLAY_MULTICAST_L2LEAFS": [ + "UNDERLAY-MULTICAST-L2LEAF1A" + ], + "IGMP_QUERIER_TESTS": [ + "IGMP-QUERIER-L3LEAF1A", + "IGMP-QUERIER-L2LEAF1A" + ], + "IGMP_QUERIER_L3LEAFS": [ + "IGMP-QUERIER-L3LEAF1A" + ], + "IGMP_QUERIER_L2LEAFS": [ + "IGMP-QUERIER-L2LEAF1A" + ], + "BGP_PEER_GROUPS": [ + "bgp-peer-groups-1", + "bgp-peer-groups-2", + "bgp-peer-groups-3" + ], + "EVPN_MULTICAST_TESTS": [ + "EVPN-MULTICAST-SPINE1", + "EVPN-MULTICAST-L2LEAF1A", + "EVPN-MULTICAST-L3LEAF1A", + "EVPN-MULTICAST-L3LEAF1B", + "EVPN-MULTICAST-L3LEAF2A", + "EVPN-MULTICAST-L3LEAF3A", + "EVPN-MULTICAST-L3LEAF3B", + "EVPN-MULTICAST-DISABLED" + ], + "EVPN_MULTICAST_TESTS_SPINES": [ + "EVPN-MULTICAST-SPINE1" + ], + "EVPN_MULTICAST_TESTS_L3LEAFS": [ + "EVPN-MULTICAST-L3LEAF1A", + "EVPN-MULTICAST-L3LEAF1B", + "EVPN-MULTICAST-L3LEAF2A", + "EVPN-MULTICAST-L3LEAF3A", + "EVPN-MULTICAST-L3LEAF3B", + "EVPN-MULTICAST-DISABLED" + ], + "EVPN_MULTICAST_L3LEAF1": [ + "EVPN-MULTICAST-L3LEAF1A", + "EVPN-MULTICAST-L3LEAF1B" + ], + "EVPN_MULTICAST_L3LEAF2": [ + "EVPN-MULTICAST-L3LEAF2A" + ], + "EVPN_MULTICAST_L3LEAF3": [ + "EVPN-MULTICAST-L3LEAF3A", + "EVPN-MULTICAST-L3LEAF3B" + ], + "EVPN_MULTICAST_DISABLED": [ + "EVPN-MULTICAST-DISABLED" + ], + "EVPN_MULTICAST_TESTS_L2LEAFS": [ + "EVPN-MULTICAST-L2LEAF1A" + ], + "BGP_FROM_NETWORK_SERVICES": [ + "bgp-from-network-services-1", + "bgp-from-network-services-2" + ], + "SVI_PROFILE_TESTS": [ + "SVI_PROFILE_NODE_1", + "SVI_PROFILE_NODE_2" + ], + "RD_RT_ADMIN_SUBFIELD_TESTS": [ + "RD-RT-ADMIN-SUBFIELD-L3LEAF1", + "RD-RT-ADMIN-SUBFIELD-L3LEAF2", + "RD-RT-ADMIN-SUBFIELD-L3LEAF3", + "RD-RT-ADMIN-SUBFIELD-L3LEAF4", + "RD-RT-ADMIN-SUBFIELD-L3LEAF5", + "RD-RT-ADMIN-SUBFIELD-L3LEAF6", + "RD-RT-ADMIN-SUBFIELD-L3LEAF7" + ], + "CUSTOM_TEMPLATES_TESTS": [ + "CUSTOM-TEMPLATES-SPINE1", + "CUSTOM-TEMPLATES-L3LEAF1A", + "CUSTOM-TEMPLATES-L3LEAF1B", + "CUSTOM-TEMPLATES-L2LEAF1A", + "CUSTOM-TEMPLATES-L2LEAF1B" + ], + "CUSTOM_TEMPLATES_SPINES": [ + "CUSTOM-TEMPLATES-SPINE1" + ], + "CUSTOM_TEMPLATES_L3LEAFS": [ + "CUSTOM-TEMPLATES-L3LEAF1A", + "CUSTOM-TEMPLATES-L3LEAF1B" + ], + "CUSTOM_TEMPLATES_L2LEAFS": [ + "CUSTOM-TEMPLATES-L2LEAF1A", + "CUSTOM-TEMPLATES-L2LEAF1B" + ], + "CUSTOM_PYTHON_MODULES_TESTS": [ + "CUSTOM-PYTHON_MODULES-SPINE1", + "CUSTOM-PYTHON_MODULES-L3LEAF1A", + "CUSTOM-PYTHON_MODULES-L3LEAF1B", + "CUSTOM-PYTHON_MODULES-L3LEAF2" + ], + "CUSTOM_PYTHON_MODULES_SPINES": [ + "CUSTOM-PYTHON_MODULES-SPINE1" + ], + "CUSTOM_PYTHON_MODULES_L3LEAFS": [ + "CUSTOM-PYTHON_MODULES-L3LEAF1A", + "CUSTOM-PYTHON_MODULES-L3LEAF1B", + "CUSTOM-PYTHON_MODULES-L3LEAF2" + ], + "AUTO_BGP_ASN": [ + "AUTO_BGP_ASN_LEAF1A", + "AUTO_BGP_ASN_LEAF1B", + "AUTO_BGP_ASN_LEAF2", + "AUTO_BGP_ASN_LEAF3A", + "AUTO_BGP_ASN_LEAF3B", + "AUTO_BGP_ASN_LEAF4A", + "AUTO_BGP_ASN_LEAF4B", + "AUTO_BGP_ASN_LEAF5A", + "AUTO_BGP_UNGROUPED_LEAF6", + "AUTO_BGP_ASN_LEAF7A", + "AUTO_BGP_ASN_LEAF7B", + "AUTO_BGP_ASN_LEAF8A", + "AUTO_BGP_ASN_LEAF8B" + ], + "AUTO_NODE_TYPE": [ + "AUTO_NODE_TYPE_SPINE01", + "AUTO_NODE_TYPE_SPINE02", + "AUTO_NODE_TYPE_LEAF01", + "AUTO_NODE_TYPE_UNGROUPED_LEAF02" + ], + "OVERLAY_ROUTING_PROTOCOL_HER_TESTS": [ + "OVERLAY_ROUTING_PROTOCOL_HER_L3LEAF1", + "OVERLAY_ROUTING_PROTOCOL_HER_L3LEAF2", + "OVERLAY_ROUTING_PROTOCOL_HER_L3LEAF3A", + "OVERLAY_ROUTING_PROTOCOL_HER_L3LEAF3B" + ], + "OVERLAY_ROUTING_PROTOCOL_CVX_TESTS": [ + "OVERLAY_ROUTING_PROTOCOL_CVX_L3LEAF1", + "OVERLAY_ROUTING_PROTOCOL_CVX_L3LEAF2", + "OVERLAY_ROUTING_PROTOCOL_CVX_SERVER1", + "OVERLAY_ROUTING_PROTOCOL_CVX_SERVER2" + ], + "UNDERLAY_FILTER_PEER_AS_TESTS": [ + "UNDERLAY_FILTER_PEER_AS_L3LEAF1", + "UNDERLAY_FILTER_PEER_AS_SPINE1", + "UNDERLAY_FILTER_PEER_AS_SPINE2" + ], + "PTP_TESTS": [ + "ptp-tests-spine1", + "ptp-tests-spine2", + "ptp-tests-spine3", + "ptp-tests-leaf1", + "ptp-tests-leaf2", + "ptp-tests-l2leaf1-ptp-disabled", + "ptp-tests-l2leaf2-ptp-enabled", + "ptp-tests-l2leaf2-ptp-enabled-uplink-disabled" + ], + "PTP_TESTS_SPINES": [ + "ptp-tests-spine1", + "ptp-tests-spine2", + "ptp-tests-spine3" + ], + "PTP_TESTS_LEAFS": [ + "ptp-tests-leaf1", + "ptp-tests-leaf2" + ], + "PTP_TESTS_L2LEAFS": [ + "ptp-tests-l2leaf1-ptp-disabled", + "ptp-tests-l2leaf2-ptp-enabled", + "ptp-tests-l2leaf2-ptp-enabled-uplink-disabled" + ], + "SFLOW_TESTS": [ + "sflow-tests-spine1", + "sflow-tests-spine2", + "sflow-tests-leaf1", + "sflow-tests-leaf2", + "sflow-tests-l2-leaf1", + "sflow-tests-l2-leaf2", + "sflow-tests-leaf3", + "sflow-tests-leaf4" + ], + "SFLOW_TESTS_SPINES": [ + "sflow-tests-spine1", + "sflow-tests-spine2" + ], + "SFLOW_TESTS_LEAFS": [ + "sflow-tests-leaf1", + "sflow-tests-leaf2", + "sflow-tests-leaf3", + "sflow-tests-leaf4" + ], + "SFLOW_TESTS_LEAF_MLAG": [ + "sflow-tests-leaf3", + "sflow-tests-leaf4" + ], + "SFLOW_TESTS_L2_LEAFS": [ + "sflow-tests-l2-leaf1", + "sflow-tests-l2-leaf2" + ], + "FLOW_TRACKING_TESTS": [ + "flow-tracking-tests-leaf1", + "flow-tracking-tests-l2-leaf1", + "flow-tracking-tests-l2-leaf2", + "flow-tracking-tests-spine1", + "flow-tracking-tests-spine2", + "flow-tracking-tests-leaf2", + "flow-tracking-tests-leaf4", + "flow-tracking-tests-leaf3" + ], + "FLOW_TRACKING_TESTS_SPINES": [ + "flow-tracking-tests-spine1", + "flow-tracking-tests-spine2" + ], + "FLOW_TRACKING_TESTS_SPINES_1": [ + "flow-tracking-tests-spine1" + ], + "FLOW_TRACKING_TESTS_SPINES_2": [ + "flow-tracking-tests-spine2" + ], + "FLOW_TRACKING_TESTS_LEAFS": [ + "flow-tracking-tests-leaf1", + "flow-tracking-tests-leaf2", + "flow-tracking-tests-leaf4", + "flow-tracking-tests-leaf3" + ], + "FLOW_TRACKING_TESTS_LEAFS_2": [ + "flow-tracking-tests-leaf2" + ], + "FLOW_TRACKING_TESTS_LEAF_MLAG": [ + "flow-tracking-tests-leaf4", + "flow-tracking-tests-leaf3" + ], + "FLOW_TRACKING_TESTS_LEAFS_3": [ + "flow-tracking-tests-leaf3" + ], + "FLOW_TRACKING_TESTS_L2_LEAFS": [ + "flow-tracking-tests-l2-leaf1", + "flow-tracking-tests-l2-leaf2" + ], + "SNMP_SETTINGS_TESTS": [ + "SNMP_SYSTEM_MAC_ENGINEID_1", + "SNMP_SYSTEM_MAC_ENGINEID_2", + "SNMP_AUTOGEN_ENGINEID", + "snmp-settings-1", + "snmp-settings-2" + ], + "UNDERLAY_PEER_FILTER_TESTS": [ + "underlay_filter_peer_as_evpn_1", + "underlay_filter_peer_as_evpn_2", + "underlay_filter_peer_as_evpn_3" + ], + "L3_EDGE_TESTS": [ + "l3_edge_bgp", + "l3_edge_ospf", + "l3_edge_isis", + "l3_edge_multicast" + ], + "UPLINK_NATIVE_VLAN_TESTS": [ + "uplink-native-vlan-grandparent", + "uplink-native-vlan-parent", + "uplink-native-vlan-child" + ], + "INBAND_MGMT_TESTS": [ + "inband-mgmt-parent", + "inband-mgmt-parent-vrf", + "inband-mgmt-subnet", + "inband-mgmt-subnet-vrf", + "inband-mgmt-ip", + "inband-mgmt-parent-dualstack1", + "inband-mgmt-parent-dualstack2", + "inband-mgmt-dualstack-subnets", + "inband-mgmt-dualstack-ips", + "inband-mgmt-parent-ipv6-1", + "inband-mgmt-parent-ipv6-2", + "inband-mgmt-ipv6-only", + "inband-mgmt-ipv6-only-vrf", + "inband-mgmt-mlag-a", + "inband-mgmt-mlag-b" + ], + "MGMT_GATEWAY_TESTS": [ + "TEST-MGMT-GATEWAY-IN-NODE-GROUP" + ], + "WAN_TESTS": [ + "legacy-autovpn-rr1", + "legacy-autovpn-rr2", + "legacy-autovpn-edge", + "legacy-autovpn-edge-no-default-policy", + "cv-pathfinder-edge-no-default-policy", + "cv-pathfinder-edge-custom-default-policy", + "cv-pathfinder-edge2A", + "cv-pathfinder-edge2B", + "site-ha-enabled-leaf2A", + "site-ha-enabled-leaf2B", + "cv-pathfinder-transit1A", + "cv-pathfinder-transit1B", + "site-ha-enabled-leaf1", + "cv-pathfinder-edge3A", + "cv-pathfinder-edge3B", + "cv-pathfinder-edge4A", + "cv-pathfinder-edge4B", + "cv-pathfinder-edge", + "cv-pathfinder-edge1", + "site-ha-disabled-leaf", + "cv-pathfinder-pathfinder", + "cv-pathfinder-pathfinder1", + "cv-pathfinder-pathfinder2", + "cv-pathfinder-custom-control-plane-policy-edge-1", + "cv-pathfinder-custom-control-plane-policy-pathfinder-1", + "cv-pathfinder-custom-control-plane-policy-edge-2", + "cv-pathfinder-custom-control-plane-policy-edge-3" + ], + "LEGACY_AUTOVPN_TESTS": [ + "legacy-autovpn-rr1", + "legacy-autovpn-rr2", + "legacy-autovpn-edge" + ], + "CV_PATHFINDER_TESTS": [ + "cv-pathfinder-edge2A", + "cv-pathfinder-edge2B", + "site-ha-enabled-leaf2A", + "site-ha-enabled-leaf2B", + "cv-pathfinder-transit1A", + "cv-pathfinder-transit1B", + "site-ha-enabled-leaf1", + "cv-pathfinder-edge3A", + "cv-pathfinder-edge3B", + "cv-pathfinder-edge4A", + "cv-pathfinder-edge4B", + "cv-pathfinder-edge", + "cv-pathfinder-edge1", + "site-ha-disabled-leaf", + "cv-pathfinder-pathfinder", + "cv-pathfinder-pathfinder1", + "cv-pathfinder-pathfinder2", + "cv-pathfinder-custom-control-plane-policy-edge-1", + "cv-pathfinder-custom-control-plane-policy-pathfinder-1", + "cv-pathfinder-custom-control-plane-policy-edge-2", + "cv-pathfinder-custom-control-plane-policy-edge-3" + ], + "SITE_HA_ENABLED": [ + "cv-pathfinder-edge2A", + "cv-pathfinder-edge2B", + "site-ha-enabled-leaf2A", + "site-ha-enabled-leaf2B" + ], + "TRANSIT_SITE_HA_ENABLED": [ + "cv-pathfinder-transit1A", + "cv-pathfinder-transit1B", + "site-ha-enabled-leaf1" + ], + "SITE_DIRECT_HA": [ + "cv-pathfinder-edge3A", + "cv-pathfinder-edge3B" + ], + "SITE_DIRECT_HA_PORT_CHANNEL": [ + "cv-pathfinder-edge4A", + "cv-pathfinder-edge4B" + ], + "SITE_HA_DISABLED": [ + "cv-pathfinder-edge", + "cv-pathfinder-edge1", + "site-ha-disabled-leaf" + ], + "CV_PATHFINDERS": [ + "cv-pathfinder-pathfinder", + "cv-pathfinder-pathfinder1", + "cv-pathfinder-pathfinder2", + "cv-pathfinder-custom-control-plane-policy-edge-1", + "cv-pathfinder-custom-control-plane-policy-pathfinder-1", + "cv-pathfinder-custom-control-plane-policy-edge-2", + "cv-pathfinder-custom-control-plane-policy-edge-3" + ], + "CV_PATHFINDER_MULTI_RR_TESTS": [ + "cv-pathfinder-pathfinder1", + "cv-pathfinder-pathfinder2" + ], + "CV_PATHFINDER_CUSTOM_CONTROL_PLANE_POLICY_TESTS": [ + "cv-pathfinder-custom-control-plane-policy-edge-1", + "cv-pathfinder-custom-control-plane-policy-pathfinder-1", + "cv-pathfinder-custom-control-plane-policy-edge-2", + "cv-pathfinder-custom-control-plane-policy-edge-3" + ], + "WAN_UNIT_TESTS": [ + "legacy-autovpn-edge-no-default-policy", + "cv-pathfinder-edge-no-default-policy", + "cv-pathfinder-edge-custom-default-policy" + ], + "UPLINK_P2P_VRFS_TESTS": [ + "UPLINK_P2P_VRFS_TESTS_SPINE1", + "UPLINK_P2P_VRFS_TESTS_SPINE2", + "UPLINK_P2P_VRFS_TESTS_LEAF1", + "UPLINK_P2P_VRFS_TESTS_L2LEAF1" + ], + "UPLINK_LAN_TESTS": [ + "uplink_lan_l2leaf", + "uplink_lan_wan_router1", + "uplink_lan_wan_router2" + ], + "DOWNLINK_POOLS_TESTS": [ + "downlink-pools-spine1", + "downlink-pools-spine2", + "downlink-pools-l3leaf1", + "downlink-pools-l3leaf2", + "downlink-pools-l3leaf3", + "downlink-pools-l3leaf4" + ], + "SINGLE_LINK_TO_MLAG_PAIR": [ + "SL-LEAF0A", + "SL-LEAF0B", + "SL-LEAF1A", + "SL-LEAF1B", + "SL-MLEAF1", + "SL-LEAF2A", + "SL-LEAF2B" + ], + "AVD_LAB": [ + "MH-L2LEAF1A", + "DC1-SPINE1", + "DC1-SPINE2", + "DC1-SPINE3", + "DC1-SPINE4", + "MH-LEAF1A", + "MH-LEAF1B", + "MH-LEAF2A", + "DC1-L2LEAF1A", + "DC1-L2LEAF1B", + "DC1-L2LEAF2A", + "DC1-L2LEAF2B", + "DC1-L2LEAF3A", + "DC1-L2LEAF4A", + "DC1.L2LEAF5A", + "DC1.L2LEAF5B", + "DC1.L2LEAF6A", + "DC1.L2LEAF6B", + "mgmt_interface_default", + "mgmt_interface_fabric", + "mgmt_interface_host", + "mgmt_interface_platform", + "DC1-LEAF1A", + "DC1-LEAF2A", + "DC1-LEAF2B", + "DC1-SVC3A", + "DC1-SVC3B", + "DC1-BL1A", + "DC1-BL1B", + "DC1-BL2A", + "DC1-BL2B", + "DC1-CL1A", + "DC1-CL1B", + "evpn_services_l2_only_true", + "evpn_services_l2_only_false", + "DC1_UNDEPLOYED_LEAF1A", + "DC1_UNDEPLOYED_LEAF1B", + "MLAG-OSPF-L3LEAF1A", + "MLAG-OSPF-L3LEAF1B" + ], + "DC1_FABRIC": [ + "DC1-SPINE1", + "DC1-SPINE2", + "DC1-SPINE3", + "DC1-SPINE4", + "MH-L2LEAF1A", + "MH-LEAF1A", + "MH-LEAF1B", + "MH-LEAF2A", + "DC1-L2LEAF1A", + "DC1-L2LEAF1B", + "DC1-L2LEAF2A", + "DC1-L2LEAF2B", + "DC1-L2LEAF3A", + "DC1-L2LEAF4A", + "DC1.L2LEAF5A", + "DC1.L2LEAF5B", + "DC1.L2LEAF6A", + "DC1.L2LEAF6B", + "mgmt_interface_default", + "mgmt_interface_fabric", + "mgmt_interface_host", + "mgmt_interface_platform", + "DC1-LEAF1A", + "DC1-LEAF2A", + "DC1-LEAF2B", + "DC1-SVC3A", + "DC1-SVC3B", + "DC1-BL1A", + "DC1-BL1B", + "DC1-BL2A", + "DC1-BL2B", + "DC1-CL1A", + "DC1-CL1B", + "evpn_services_l2_only_true", + "evpn_services_l2_only_false", + "DC1_UNDEPLOYED_LEAF1A", + "DC1_UNDEPLOYED_LEAF1B", + "MLAG-OSPF-L3LEAF1A", + "MLAG-OSPF-L3LEAF1B" + ], + "DC1_SPINES": [ + "DC1-SPINE1", + "DC1-SPINE2", + "DC1-SPINE3", + "DC1-SPINE4" + ], + "DC1_LEAFS": [ + "DC1-LEAF1A", + "DC1-LEAF2A", + "DC1-LEAF2B", + "DC1-SVC3A", + "DC1-SVC3B", + "DC1-BL1A", + "DC1-BL1B", + "DC1-BL2A", + "DC1-BL2B", + "DC1-CL1A", + "DC1-CL1B", + "evpn_services_l2_only_true", + "evpn_services_l2_only_false", + "DC1_UNDEPLOYED_LEAF1A", + "DC1_UNDEPLOYED_LEAF1B" + ], + "DC1_LEAF1": [ + "DC1-LEAF1A" + ], + "DC1_LEAF2": [ + "DC1-LEAF2A", + "DC1-LEAF2B" + ], + "DC1_SVC3": [ + "DC1-SVC3A", + "DC1-SVC3B" + ], + "DC1_BL1": [ + "DC1-BL1A", + "DC1-BL1B" + ], + "DC1_BL2": [ + "DC1-BL2A", + "DC1-BL2B" + ], + "DC1_CL1": [ + "DC1-CL1A", + "DC1-CL1B" + ], + "UNIT_TESTS": [ + "evpn_services_l2_only_true", + "evpn_services_l2_only_false" + ], + "DC1_UNDEPLOYED_LEAF1": [ + "DC1_UNDEPLOYED_LEAF1A", + "DC1_UNDEPLOYED_LEAF1B" + ], + "DC1_L2LEAFS": [ + "DC1-L2LEAF1A", + "DC1-L2LEAF1B", + "DC1-L2LEAF2A", + "DC1-L2LEAF2B", + "DC1-L2LEAF3A", + "DC1-L2LEAF4A", + "DC1.L2LEAF5A", + "DC1.L2LEAF5B", + "DC1.L2LEAF6A", + "DC1.L2LEAF6B", + "mgmt_interface_default", + "mgmt_interface_fabric", + "mgmt_interface_host", + "mgmt_interface_platform" + ], + "DC1_L2LEAF1": [ + "DC1-L2LEAF1A", + "DC1-L2LEAF1B" + ], + "DC1_L2LEAF2": [ + "DC1-L2LEAF2A", + "DC1-L2LEAF2B" + ], + "DC1_L2LEAF3": [ + "DC1-L2LEAF3A" + ], + "DC1_L2LEAF4": [ + "DC1-L2LEAF4A" + ], + "DC1_L2LEAF5": [ + "DC1.L2LEAF5A", + "DC1.L2LEAF5B" + ], + "DC1_L2LEAF6": [ + "DC1.L2LEAF6A", + "DC1.L2LEAF6B" + ], + "TESTS": [ + "mgmt_interface_default", + "mgmt_interface_fabric", + "mgmt_interface_host", + "mgmt_interface_platform" + ], + "MH_LEAFS_TESTS": [ + "MH-LEAF1A", + "MH-LEAF1B", + "MH-LEAF2A" + ], + "MH_L3LEAF1": [ + "MH-LEAF1A", + "MH-LEAF1B" + ], + "MH_L3LEAF2": [ + "MH-LEAF2A" + ], + "MH_L2LEAFS_TESTS": [ + "MH-L2LEAF1A" + ], + "MLAG_OSPF_TESTS": [ + "MLAG-OSPF-L3LEAF1A", + "MLAG-OSPF-L3LEAF1B" + ], + "MLAG_OSPF_L3LEAF1": [ + "MLAG-OSPF-L3LEAF1A", + "MLAG-OSPF-L3LEAF1B" + ], + "DC1_TENANTS_NETWORKS": [ + "DC1-L2LEAF1A", + "DC1-L2LEAF1B", + "DC1-L2LEAF2A", + "DC1-L2LEAF2B", + "DC1-L2LEAF3A", + "DC1-L2LEAF4A", + "DC1.L2LEAF5A", + "DC1.L2LEAF5B", + "DC1.L2LEAF6A", + "DC1.L2LEAF6B", + "mgmt_interface_default", + "mgmt_interface_fabric", + "mgmt_interface_host", + "mgmt_interface_platform", + "DC1-LEAF1A", + "DC1-LEAF2A", + "DC1-LEAF2B", + "DC1-SVC3A", + "DC1-SVC3B", + "DC1-BL1A", + "DC1-BL1B", + "DC1-BL2A", + "DC1-BL2B", + "DC1-CL1A", + "DC1-CL1B", + "evpn_services_l2_only_true", + "evpn_services_l2_only_false", + "DC1_UNDEPLOYED_LEAF1A", + "DC1_UNDEPLOYED_LEAF1B" + ], + "DC1_SERVERS": [ + "DC1-L2LEAF1A", + "DC1-L2LEAF1B", + "DC1-L2LEAF2A", + "DC1-L2LEAF2B", + "DC1-L2LEAF3A", + "DC1-L2LEAF4A", + "DC1.L2LEAF5A", + "DC1.L2LEAF5B", + "DC1.L2LEAF6A", + "DC1.L2LEAF6B", + "mgmt_interface_default", + "mgmt_interface_fabric", + "mgmt_interface_host", + "mgmt_interface_platform", + "DC1-LEAF1A", + "DC1-LEAF2A", + "DC1-LEAF2B", + "DC1-SVC3A", + "DC1-SVC3B", + "DC1-BL1A", + "DC1-BL1B", + "DC1-BL2A", + "DC1-BL2B", + "DC1-CL1A", + "DC1-CL1B", + "evpn_services_l2_only_true", + "evpn_services_l2_only_false", + "DC1_UNDEPLOYED_LEAF1A", + "DC1_UNDEPLOYED_LEAF1B" + ], + "MH_TENANT_NETWORKS": [ + "MH-L2LEAF1A", + "MH-LEAF1A", + "MH-LEAF1B", + "MH-LEAF2A" + ], + "MH_SERVERS": [ + "MH-L2LEAF1A", + "MH-LEAF1A", + "MH-LEAF1B", + "MH-LEAF2A" + ], + "DUPLICATE_SVIS_L2VLANS": [ + "DUP-LEAF1", + "DUP-LEAF2" + ], + "PLATFORM_SETTINGS_TESTS": [ + "7010TX-LEAF1", + "7010TX-LEAF2" + ] + }, + "ansible_version": { + "string": "2.17.0", + "full": "2.17.0", + "major": 2, + "minor": 17, + "revision": 0 + }, + "ansible_check_mode": false, + "ansible_diff_mode": false, + "ansible_forks": 10, + "ansible_inventory_sources": [ + "/home/holbech/avd/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/inventory/hosts.yml" + ], + "ansible_skip_tags": [], + "ansible_run_tags": [ + "all" + ], + "ansible_verbosity": 0 +} \ No newline at end of file diff --git a/python-avd/tests/schema_tools/artifacts/README.md b/python-avd/tests/schema_tools/artifacts/README.md new file mode 100644 index 00000000000..9d8c95d0d4e --- /dev/null +++ b/python-avd/tests/schema_tools/artifacts/README.md @@ -0,0 +1,11 @@ + + +The files in this directory are frozen copies of the real schema and and data. +This is to ensure the tests of the schema tooling itself are consistent as the data models evolve. +The fully updated schemas are tested with the updated data under the `tests/pyavd/eos_cli_config_gen` and `tests/pyavd/eos_designs` folders. + +The files in the ./output folder are temporary files generated by the tests. diff --git a/python-avd/tests/schema_tools/artifacts/eos_cli_config_gen.schema.yml b/python-avd/tests/schema_tools/artifacts/eos_cli_config_gen.schema.yml index 13f47f1f485..cb65a594d50 100644 --- a/python-avd/tests/schema_tools/artifacts/eos_cli_config_gen.schema.yml +++ b/python-avd/tests/schema_tools/artifacts/eos_cli_config_gen.schema.yml @@ -1,8 +1,11 @@ -# Copyright (c) 2023 Arista Networks, Inc. +# Copyright (c) 2024 Arista Networks, Inc. # Use of this source code is governed by the Apache License 2.0 # that can be found in the LICENSE file. -# yaml-language-server: $schema=../../../pyavd/_schema/avd_meta_schema.json +# yaml-language-server: $schema=../../_schema/avd_meta_schema.json +# Line above is used by RedHat's YAML Schema vscode extension +# Use Ctrl + Space to get suggestions for every field. Autocomplete will pop up after typing 2 letters. $id: eos_cli_config_gen +$schema: avd_meta_schema type: dict allow_other_keys: true keys: @@ -22,7 +25,7 @@ keys: - start-stop - stop-only group: - description: Group Name + description: Group Name. type: str logging: type: bool @@ -36,7 +39,7 @@ keys: - start-stop - stop-only group: - description: Group Name + description: Group Name. type: str logging: type: bool @@ -53,7 +56,7 @@ keys: - start-stop - stop-only group: - description: Group Name + description: Group Name. type: str dot1x: type: dict @@ -67,7 +70,7 @@ keys: - start-stop - stop-only group: - description: Group Name + description: Group Name. type: str commands: type: dict @@ -81,7 +84,7 @@ keys: type: str convert_types: - int - description: Privilege level 'all' or 0-15 + description: Privilege level 'all' or 0-15. type: type: str valid_values: @@ -89,7 +92,7 @@ keys: - start-stop - stop-only group: - description: Group Name + description: Group Name. type: str logging: type: bool @@ -102,7 +105,7 @@ keys: type: str convert_types: - int - description: Privilege level 'all' or 0-15 + description: Privilege level 'all' or 0-15. type: type: str valid_values: @@ -110,7 +113,7 @@ keys: - start-stop - stop-only group: - description: Group Name + description: Group Name. type: str logging: type: bool @@ -268,7 +271,7 @@ keys: keys: level: type: str - description: Privilege level(s) 0-15 + description: Privilege level(s) 0-15. convert_types: - int default: @@ -281,10 +284,15 @@ keys: - "group MYGROUP none" - - "group tacacs+ group MYGROUP local"' + - "group tacacs+ group MYGROUP local" + + ' aaa_root: type: dict keys: + disabled: + type: bool + description: Set to `true` to configure `no aaa root` which is the EOS default. secret: type: dict keys: @@ -296,7 +304,7 @@ keys: type: dict keys: name: - description: Group name + description: Group name. type: str type: type: str @@ -311,10 +319,10 @@ keys: keys: server: type: str - description: Hostname or IP address + description: Hostname or IP address. vrf: type: str - description: VRF name + description: VRF name. convert_types: - int access_lists: @@ -326,9 +334,18 @@ keys: keys: name: type: str - description: Access-list Name + description: Access-list Name. + convert_types: + - int counters_per_entry: type: bool + permit_response_traffic: + type: str + valid_values: + - nat + description: 'Permit response traffic automatically based on NAT translations. + + Minimum EOS version requirement 4.32.2F.' sequence_numbers: type: list required: true @@ -338,15 +355,17 @@ keys: keys: sequence: type: int - description: Sequence ID + description: Sequence ID. convert_types: - str action: type: str required: true - description: 'Action as string + description: 'Action as string. + + Example: "deny ip any any" - Example: "deny ip any any"' + ' address_locking: type: dict keys: @@ -354,10 +373,10 @@ keys: type: list items: type: str - description: DHCP server IPv4 address + description: DHCP server IPv4 address. disabled: type: bool - description: Disable IP locking on configured ports + description: Disable IP locking on configured ports. leases: type: list items: @@ -366,11 +385,11 @@ keys: ip: type: str required: true - description: IP address + description: IP address. mac: type: str required: true - description: MAC address (hhhh.hhhh.hhhh or hh:hh:hh:hh:hh:hh) + description: MAC address (hhhh.hhhh.hhhh or hh:hh:hh:hh:hh:hh). local_interface: type: str locked_address: @@ -378,29 +397,301 @@ keys: keys: expiration_mac_disabled: type: bool - description: Configure deauthorizing locked addresses upon MAC aging out + description: Configure deauthorizing locked addresses upon MAC aging out. ipv4_enforcement_disabled: type: bool - description: Configure enforcement for locked IPv4 addresses + description: Configure enforcement for locked IPv4 addresses. ipv6_enforcement_disabled: type: bool - description: Configure enforcement for locked IPv6 addresses + description: Configure enforcement for locked IPv6 addresses. + agents: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: Agent name. + environment_variables: + type: list + primary_key: name + min_length: 1 + items: + type: dict + keys: + name: + type: str + description: Environment variable name. + value: + type: str + convert_types: + - int + - bool + required: true + description: Environment variable value. aliases: type: str description: "Multi-line string with one or more alias commands.\n\nExample:\n\n```yaml\naliases: |\n alias wr copy running-config startup-config\n alias siib show ip interface - brief\n```" + brief\n```\n" + application_traffic_recognition: + type: dict + description: Application traffic recognition configuration. + keys: + categories: + type: list + description: List of categories. + primary_key: name + items: + type: dict + keys: + name: + type: str + description: Category name. + applications: + type: list + description: List of applications. + items: + type: dict + keys: + name: + type: str + description: Application name. + service: + type: str + description: 'Service Name. + + Specific service to target for this application. + + If no service is specified, all supported services of the application + are matched. + + Not all valid values are valid for all applications, check on + EOS CLI.' + valid_values: + - audio-video + - chat + - default + - file-transfer + - networking-protocols + - peer-to-peer + - software-update + field_sets: + type: dict + keys: + l4_ports: + type: list + primary_key: name + description: L4 port field-set. + items: + type: dict + keys: + name: + type: str + description: L4 port field-set name. + port_values: + type: list + items: + type: str + convert_types: + - int + description: 'Port values or range of port values. + + Port values are between 0 and 65535.' + ipv4_prefixes: + type: list + primary_key: name + description: IPv4 prefix field set. + items: + type: dict + keys: + name: + type: str + description: IPv4 prefix field-set name. + prefix_values: + type: list + items: + type: str + description: IP prefix (ex 1.2.3.0/24). + applications: + type: dict + keys: + ipv4_applications: + type: list + description: List of user defined IPv4 applications. The name should be + unique over all defined applications (ipv4 and l4). + primary_key: name + items: + type: dict + $ref: eos_cli_config_gen#/$defs/application_traffic_recognition_application + keys: + name: + type: str + description: Application name. + src_prefix_set_name: + type: str + description: Source prefix set name. + dest_prefix_set_name: + type: str + description: Destination prefix set name. + dscp_ranges: + type: list + description: 'Accept DSCP value(s) or range(s). + + DSCP values can be between 0 and 63. + + Other valid values are cs0 to cs7, af11-13, af21-23, af31-33, + af41-af43 and ef. + + Note: The values are not sorted so the list items need to be supplied + in the right order to match the CLI if required.' + items: + type: str + convert_types: + - int + description: DSCP value or range syntax. + pattern: ^(?:cs[1-7]|af[1-4][1-3]|ef|(?:(?:,|,\s|^)(?:\d|[1-5]\d|6[0-3])(?:-(?:\d|[1-5]\d|6[0-3]))?)+)$ + l4_applications: + type: list + description: List of user defined L4 applications. The name should be + unique over all defined applications (ipv4 and l4). + primary_key: name + items: + type: dict + $ref: eos_cli_config_gen#/$defs/application_traffic_recognition_application + keys: + name: + type: str + description: Application name. + application_profiles: + type: list + description: Group of applications. + items: + type: dict + keys: + name: + type: str + description: Application Profile name. + applications: + type: list + description: List of applications part of the application profile. + items: + type: dict + keys: + name: + type: str + description: Application Name. + service: + type: str + description: 'Service Name. + + Specific service to target for this application. + + If no service is specified, all supported services of the application + are matched. + + Not all valid values are valid for all applications, check on + EOS CLI.' + valid_values: + - audio-video + - chat + - default + - file-transfer + - networking-protocols + - peer-to-peer + - software-update + application_transports: + type: list + description: List of transport protocols. + items: + type: str + description: Transport name. + valid_values: + - http + - https + - udp + - tcp + - ip + - ip6 + - ssl + - rtp + - sctp + - quic + categories: + type: list + description: Categories under this application profile. + items: + type: dict + keys: + name: + type: str + description: Name of a category. + service: + type: str + description: 'Service Name. + + Specific service to target for this application. + + If no service is specified, all supported services of the application + are matched. + + Not all valid values are valid for all applications, check on + EOS CLI.' + valid_values: + - audio-video + - chat + - default + - file-transfer + - networking-protocols + - peer-to-peer + - software-update arp: type: dict keys: + persistent: + type: dict + keys: + enabled: + type: bool + required: true + description: Restore the ARP cache after reboot. + refresh_delay: + type: int + description: Time to wait in seconds before refreshing the ARP cache after + reboot (EOS default 600). + min: 600 + max: 3600 + convert_types: + - str aging: type: dict keys: timeout_default: - description: Timeout in seconds + description: Timeout in seconds. type: int min: 60 max: 65535 + static_entries: + type: list + description: Static ARP entries. + items: + type: dict + keys: + ipv4_address: + type: str + required: true + description: ARP entry IPv4 address. + vrf: + type: str + convert_types: + - int + description: ARP entry VRF. + mac_address: + type: str + description: ARP entry MAC address. + required: true + pattern: ^[0-9A-Fa-f]{4}\.[0-9A-Fa-f]{4}\.[0-9A-Fa-f]{4}$ as_path: type: dict keys: @@ -416,7 +707,7 @@ keys: keys: name: type: str - description: Access List Name + description: Access List Name. entries: type: list items: @@ -429,7 +720,7 @@ keys: - deny match: type: str - description: Regex To Match + description: Regex To Match. origin: type: str valid_values: @@ -438,6 +729,17 @@ keys: - igp - incomplete default: any + avd_data_conversion_mode: + documentation_options: + table: role-input-validation + type: str + deprecation: + warning: true + removed: true + remove_in_version: 5.0.0 + description: 'Conversion Mode for AVD input data conversion. + + ' avd_data_validation_mode: documentation_options: table: role-input-validation @@ -455,16 +757,18 @@ keys: "error" will produce error messages and fail the task. - "warning" will produce warning messages.' + "warning" will produce warning messages. + + ' banners: type: dict keys: login: type: str - description: Multiline string ending with EOF on the last line + description: Multiline string ending with EOF on the last line. motd: type: str - description: Multiline string ending with EOF on the last line + description: Multiline string ending with EOF on the last line. bgp_groups: type: list primary_key: name @@ -473,7 +777,7 @@ keys: keys: name: type: str - description: Group Name + description: Group Name. vrf: type: str convert_types: @@ -486,10 +790,10 @@ keys: type: list items: type: str - description: Profile Name + description: Profile Name. boot: display_name: System Boot Settings - description: 'Set the Aboot password + description: 'Set the Aboot password. ' type: dict @@ -504,7 +808,7 @@ keys: - sha512 default: sha512 key: - description: Hashed Password + description: Hashed Password. type: str class_maps: type: dict @@ -518,13 +822,15 @@ keys: keys: name: type: str - description: Class-Map Name + description: Class-Map Name. ip: type: dict keys: access_group: type: str - description: Standard Access-List Name + description: Standard Access-List Name. + convert_types: + - int qos: type: list primary_key: name @@ -533,29 +839,33 @@ keys: keys: name: type: str - description: Class-Map Name + description: Class-Map Name. vlan: type: str convert_types: - int - description: VLAN value(s) or range(s) of VLAN values + description: VLAN value(s) or range(s) of VLAN values. cos: type: str convert_types: - int - description: CoS value(s) or range(s) of CoS values + description: CoS value(s) or range(s) of CoS values. ip: type: dict keys: access_group: type: str - description: IPv4 Access-List Name + description: IPv4 Access-List Name. + convert_types: + - int ipv6: type: dict keys: access_group: type: str - description: IPv6 Access-List Name + description: IPv6 Access-List Name. + convert_types: + - int clock: type: dict keys: @@ -565,18 +875,33 @@ keys: type: list primary_key: name display_name: Community Lists (legacy model) + deprecation: + warning: true + remove_in_version: 6.0.0 + new_key: ip_community_lists items: type: dict keys: name: type: str - description: Community-list Name + description: Community-list Name. action: type: str required: true - description: 'Action as string + description: 'Action as string. + + Example: "permit GSHUT 65123:123" + + ' + config_comment: + type: str + description: 'Add a comment to provide information about the configuration. - Example: "permit GSHUT 65123:123"' + This comment will be rendered at the top of the generated configuration.' + config_end: + type: bool + description: Render `end` at the end of the configuration. + default: false custom_templates: type: list display_name: Extensibility with Custom Templates @@ -590,7 +915,7 @@ keys: `custom_templates` to group/host variables:\n" items: type: str - description: Template relative path below playbook directory + description: Template relative path below playbook directory. cvx: type: dict description: CVX server features are not supported on physical switches. See `management_cvx` @@ -602,7 +927,7 @@ keys: type: list items: type: str - description: IP address or hostname + description: IP address or hostname. services: type: dict keys: @@ -614,7 +939,7 @@ keys: keys: password: type: str - description: Hashed password using the password_type + description: Hashed password using the password_type. password_type: type: str convert_types: @@ -628,7 +953,7 @@ keys: type: bool vxlan: type: dict - description: VXLAN Controller service + description: VXLAN Controller service. keys: shutdown: type: bool @@ -648,7 +973,7 @@ keys: keys: cvaddrs: type: list - description: 'Streaming address(es) for CloudVision single cluster + description: 'Streaming address(es) for CloudVision single cluster. - TCP 9910 is used for CV on-prem @@ -657,10 +982,10 @@ keys: ' items: type: str - description: Server address in the format `:` + description: Server address in the format `:`. clusters: type: list - description: 'Multiple CloudVision clusters + description: 'Multiple CloudVision clusters. ' primary_key: name @@ -669,10 +994,10 @@ keys: keys: name: type: str - description: Cluster Name + description: Cluster Name. cvaddrs: type: list - description: 'Streaming address(es) for CloudVision cluster + description: 'Streaming address(es) for CloudVision cluster. - TCP 9910 is used for CV on-prem @@ -681,10 +1006,10 @@ keys: ' items: type: str - description: Server address in the format `:` + description: Server address in the format `:`. cvauth: type: dict - description: 'Authentication scheme used to connect to CloudVision + description: 'Authentication scheme used to connect to CloudVision. ' keys: @@ -699,35 +1024,35 @@ keys: type: str token_file: type: str - description: 'Token file path + description: 'Token file path. e.g. "/tmp/token" ' cert_file: type: str - description: 'Client certificate file path + description: 'Client certificate file path. e.g. "/persist/secure/ssl/terminattr/primary/certs/client.crt" ' ca_file: type: str - description: 'CA certificate file path (on-prem only) + description: 'CA certificate file path (on-prem only). e.g. "/persist/secure/ssl/terminattr/primary/certs/ca.crt" ' key_file: type: str - description: 'Client certificate key file path + description: 'Client certificate key file path. e.g. "/persist/secure/ssl/terminattr/primary/keys/client.key" ' cvobscurekeyfile: type: bool - description: 'Encrypt the private key used for authentication to CloudVision + description: 'Encrypt the private key used for authentication to CloudVision. ' cvproxy: @@ -736,30 +1061,33 @@ keys: when the CloudVision server is hosted in the cloud. The expected form is http://[user:password@]ip:port, e.g.: `http://arista:arista@10.83.12.78:3128`. - Available as of TerminAttr v1.13.0 + Available as of TerminAttr v1.13.0. ' cvsourceip: type: str - description: 'Set source IP address in case of in-band management + description: 'Set source IP address in case of in-band management. ' cvsourceintf: type: str description: 'Set source interface in case of in-band management. Available - as of TerminAttr v1.23.0 + as of TerminAttr v1.23.0. + + The interface name is case sensitive and has to match the interface + name in the running-config, e.g.:Vlan100. ' cvvrf: type: str - description: 'The VRF to use to connect to CloudVision + description: 'The VRF to use to connect to CloudVision. ' convert_types: - int cvauth: type: dict - description: 'Authentication scheme used to connect to CloudVision + description: 'Authentication scheme used to connect to CloudVision. ' keys: @@ -774,35 +1102,35 @@ keys: type: str token_file: type: str - description: 'Token file path + description: 'Token file path. e.g. "/tmp/token" ' cert_file: type: str - description: 'Client certificate file path + description: 'Client certificate file path. e.g. "/persist/secure/ssl/terminattr/primary/certs/client.crt" ' ca_file: type: str - description: 'CA certificate file path (on-prem only) + description: 'CA certificate file path (on-prem only). e.g. "/persist/secure/ssl/terminattr/primary/certs/ca.crt" ' key_file: type: str - description: 'Client certificate key file path + description: 'Client certificate key file path. e.g. "/persist/secure/ssl/terminattr/primary/keys/client.key" ' cvobscurekeyfile: type: bool - description: 'Encrypt the private key used for authentication to CloudVision + description: 'Encrypt the private key used for authentication to CloudVision. ' cvproxy: @@ -811,22 +1139,25 @@ keys: when the CloudVision server is hosted in the cloud. The expected form is http://[user:password@]ip:port, e.g.: `http://arista:arista@10.83.12.78:3128`. - Available as of TerminAttr v1.13.0 + Available as of TerminAttr v1.13.0. ' cvsourceip: type: str - description: 'Set source IP address in case of in-band management + description: 'Set source IP address in case of in-band management. ' cvsourceintf: type: str - description: 'Set source interface in case of in-band management + description: 'Set source interface in case of in-band management. + + The interface name is case sensitive and has to match the interface name + in the running-config, e.g.:Vlan100. ' cvvrf: type: str - description: 'The VRF to use to connect to CloudVision + description: 'The VRF to use to connect to CloudVision. ' convert_types: @@ -834,7 +1165,7 @@ keys: cvgnmi: type: bool description: 'Stream states from EOS gNMI servers (Openconfig) to CloudVision. - Available as of TerminAttr v1.13.1 + Available as of TerminAttr v1.13.1. ' disable_aaa: @@ -842,19 +1173,19 @@ keys: description: 'Disable AAA authorization and accounting. When setting this flag, all commands pushed from CloudVision are applied - directly to the CLI without authorization + directly to the CLI without authorization. ' grpcaddr: type: str - description: 'Set the gRPC server address, the default is 127.0.0.1:6042 + description: 'Set the gRPC server address, the default is 127.0.0.1:6042. e.g. "MGMT/0.0.0.0:6042" ' grpcreadonly: type: bool - description: 'gNMI read-only mode - Disable gnmi.Set() + description: 'gNMI read-only mode - Disable gnmi.Set(). ' ingestexclude: @@ -882,7 +1213,7 @@ keys: ecodhcpaddr: type: str description: 'ECO DHCP Collector address or ECO DHCP Fingerprint listening - address in standalone mode (default "127.0.0.1:67") + address in standalone mode (default "127.0.0.1:67"). ' ipfix: @@ -917,11 +1248,17 @@ keys: ' cvcompression: + deprecation: + removed: true + warning: true + remove_in_version: v5.0.0 type: str description: 'The default compression scheme when streaming to CloudVision is gzip since TerminAttr 1.6.1 and CVP 2019.1.0. - There is no need to change the compression scheme.' + There is no need to change the compression scheme. + + ' daemons: type: list primary_key: name @@ -933,11 +1270,11 @@ keys: keys: name: type: str - description: Daemon Name + description: Daemon Name. exec: type: str required: true - description: 'command to run as a daemon + description: 'command to run as a daemon. ' enabled: @@ -950,109 +1287,622 @@ keys: type: list items: type: str - description: Server IP or Hostname + description: Server IP or Hostname. tunnel_requests_disabled: type: bool - dns_domain: - type: str - description: Domain Name - domain_list: - type: list - description: Search list of DNS domains - items: - type: str - description: Domain name - dot1x: - type: dict - display_name: Global 802.1x Authentication - keys: - system_auth_control: - type: bool - protocol_lldp_bypass: - type: bool - dynamic_authorization: + mlag_peerlink_requests_disabled: type: bool - mac_based_authentication: - type: dict - keys: - delay: - type: int - min: 0 - max: 300 - convert_types: - - str - hold_period: - type: int - min: 1 - max: 300 - convert_types: - - str - radius_av_pair: - type: dict - keys: - service_type: - type: bool - framed_mtu: - type: int - min: 68 - max: 9236 - convert_types: - - str - dynamic_prefix_lists: + dhcp_servers: type: list + primary_key: vrf items: type: dict keys: - name: - type: str - description: Dynamic prefix-list name - match_map: + disabled: + type: bool + vrf: type: str - description: Route-map name - prefix_list: + description: VRF in which to configure the DHCP server, use `default` to + indicate default VRF. + convert_types: + - int + lease_time_ipv4: type: dict keys: - ipv4: - type: str - description: Prefix-list name - ipv6: - type: str - description: Prefix-list name - enable_password: - type: dict - keys: - hash_algorithm: - type: str - valid_values: - - md5 - - sha512 - key: - type: str - description: 'Must be the hash of the password using the specified algorithm. - - By default EOS salts the password, so the simplest is to generate the hash - on an EOS device.' - eos_cli: - type: str - description: Multiline string with EOS CLI rendered directly on the root level - of the final EOS configuration - eos_cli_config_gen_configuration: - type: dict + days: + type: int + convert_types: + - str + min: 0 + max: 2000 + required: true + hours: + type: int + convert_types: + - str + min: 0 + max: 23 + required: true + minutes: + type: int + convert_types: + - str + min: 0 + max: 59 + required: true + lease_time_ipv6: + type: dict + keys: + days: + type: int + convert_types: + - str + min: 0 + max: 2000 + required: true + hours: + type: int + convert_types: + - str + min: 0 + max: 23 + required: true + minutes: + type: int + convert_types: + - str + min: 0 + max: 59 + required: true + dns_domain_name_ipv4: + type: str + dns_domain_name_ipv6: + type: str + dns_servers_ipv4: + type: list + min_length: 1 + description: List of DNS servers for IPv4 clients. + items: + type: str + required: true + description: IPv4 address of DNS server. + dns_servers_ipv6: + type: list + min_length: 1 + description: List of DNS servers for IPv6 clients. + items: + type: str + required: true + description: IPv6 address of DNS server. + tftp_server: + type: dict + keys: + file_ipv4: + type: str + min_length: 1 + max_length: 255 + description: Name of TFTP file for IPv4 clients. + file_ipv6: + type: str + min_length: 1 + max_length: 255 + description: Name of TFTP file for IPv6 clients. + ipv4_vendor_options: + type: list + primary_key: vendor_id + items: + type: dict + keys: + vendor_id: + type: str + convert_types: + - int + sub_options: + type: list + primary_key: code + items: + type: dict + keys: + code: + type: int + required: true + min: 1 + max: 254 + convert_types: + - str + string: + type: str + description: 'String value for suboption data. + + Only one of `string`, `ipv4_address` and `array_ipv4_address` + variables should be used for any one suboption. + + The order of precedence if multiple of these variables are + defined is `string` -> `ipv4_address` -> `array_ipv4_address`.' + ipv4_address: + type: str + description: 'IPv4 address value for suboption data. + + Only one of `string`, `ipv4_address` and `array_ipv4_address` + variables should be used for any one suboption. + + The order of precedence if multiple of these variables are + defined is `string` -> `ipv4_address` -> `array_ipv4_address`.' + array_ipv4_address: + type: list + description: 'Array of IPv4 addresses for suboption data. + + Only one of `string`, `ipv4_address` and `array_ipv4_address` + variables should be used for any one suboption. + + The order of precedence if multiple of these variables are + defined is `string` -> `ipv4_address` -> `array_ipv4_address`.' + items: + type: str + subnets: + type: list + primary_key: subnet + items: + type: dict + keys: + subnet: + description: IPv4/IPv6 subnet. + type: str + required: true + name: + type: str + convert_types: + - int + default_gateway: + type: str + dns_servers: + type: list + items: + type: str + ranges: + type: list + items: + type: dict + keys: + start: + type: str + required: true + end: + type: str + required: true + lease_time: + type: dict + keys: + days: + type: int + required: true + min: 0 + max: 2000 + convert_types: + - str + hours: + type: int + required: true + min: 0 + max: 23 + convert_types: + - str + minutes: + type: int + required: true + min: 0 + max: 59 + convert_types: + - str + reservations: + description: DHCP client reservations. + type: list + primary_key: mac_address + items: + type: dict + keys: + mac_address: + type: str + description: Ethernet address in format - HHHH.HHHH.HHHH + hostname: + type: str + ipv4_address: + type: str + description: 'Valid IPv4 address from the given subnet. + + This should only be used within an IPv4 subnet.' + ipv6_address: + type: str + description: 'Valid IPv6 address from the given subnet. + + This should only be used within an IPv6 subnet.' + eos_cli: + type: str + description: Multiline EOS CLI rendered directly on the dhcp server in the + final EOS configuration. + dns_domain: + type: str + description: Domain Name. + domain_list: + type: list + description: Search list of DNS domains. + items: + type: str + description: Domain name. + dot1x: + type: dict + display_name: Global 802.1x Authentication + keys: + system_auth_control: + type: bool + protocol_lldp_bypass: + type: bool + protocol_bpdu_bypass: + type: bool + dynamic_authorization: + type: bool + mac_based_authentication: + type: dict + keys: + delay: + type: int + min: 0 + max: 300 + convert_types: + - str + hold_period: + type: int + min: 1 + max: 300 + convert_types: + - str + radius_av_pair_username_format: + type: dict + description: RADIUS AV-pair username settings. + keys: + delimiter: + type: str + description: Delimiter to use in MAC address string. + required: true + valid_values: + - colon + - hyphen + - none + - period + mac_string_case: + type: str + description: MAC address string in lowercase/uppercase. + required: true + valid_values: + - lowercase + - uppercase + radius_av_pair: + type: dict + keys: + service_type: + type: bool + framed_mtu: + type: int + min: 68 + max: 9236 + convert_types: + - str + aaa: + type: dict + description: Configure AAA parameters. + keys: + unresponsive: + type: dict + description: Configure AAA timeout options. + keys: + eap_response: + type: str + description: EAP response to send. + valid_values: + - success + - disabled + action: + type: dict + description: Set action for supplicant when AAA times out. + keys: + apply_cached_results: + type: bool + description: Use results from a previous AAA response. + cached_results_timeout: + type: dict + keys: + time_duration: + type: int + convert_types: + - str + min: 1 + description: 'Enable caching for a specific duration - + + <1-10000> duration in days + + <1-14400000> duration in minutes + + <1-240000> duration in hours + + <1-864000000> duration in seconds' + time_duration_unit: + type: str + required: true + valid_values: + - days + - hours + - minutes + - seconds + apply_alternate: + type: bool + description: 'Apply alternate action if primary action fails. + + eg. aaa unresponsive action apply cached-results else traffic + allow' + traffic_allow: + type: bool + description: Set action for supplicant traffic when AAA times + out. + traffic_allow_vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + phone_action: + type: dict + description: Set action for supplicant when AAA times out. + keys: + apply_cached_results: + type: bool + description: Use results from a previous AAA response. + cached_results_timeout: + type: dict + keys: + time_duration: + type: int + convert_types: + - str + min: 1 + description: 'Enable caching for a specific duration - + + <1-10000> duration in days + + <1-14400000> duration in minutes + + <1-240000> duration in hours + + <1-864000000> duration in seconds' + time_duration_unit: + type: str + required: true + valid_values: + - days + - hours + - minutes + - seconds + apply_alternate: + type: bool + description: 'Apply alternate action if primary action fails. + + eg. aaa unresponsive phone action apply cached-results else + traffic allow' + traffic_allow: + description: Set action for supplicant traffic when AAA times + out. + type: bool + recovery_action_reauthenticate: + type: bool + accounting_update_interval: + type: int + convert_types: + - str + min: 5 + max: 65535 + description: Interval period in seconds. + captive_portal: + type: dict + description: Web authentication feature authenticates a supplicant through + a web page, referred to as a captive portal. + keys: + enabled: + type: bool + required: true + url: + type: str + description: "Supported URL type:\n - http: http://[:]\n + \ - https: https://[:]" + ssl_profile: + type: str + start_limit_infinite: + type: bool + description: Set captive-portal start limit to infinite. + access_list_ipv4: + type: str + description: Standard access-list name. + supplicant: + type: dict + keys: + profiles: + description: Dot1x supplicant profiles. + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + eap_method: + type: str + description: "Extensible Authentication Protocol method:\n - EAP + Flexible Authentication via Secure Tunneling.\n - EAP with Transport + Layer Security." + valid_values: + - fast + - tls + identity: + type: str + description: User identity. + passphrase_type: + type: str + convert_types: + - int + valid_values: + - '0' + - '7' + - 8a + default: '7' + passphrase: + type: str + description: Extensible Authentication Protocol password. + ssl_profile: + type: str + logging: + type: bool + description: Enable supplicant logging. + disconnect_cached_results_timeout: + type: int + convert_types: + - str + min: 60 + max: 65535 + description: Timeout in seconds for removing a disconnected supplicant. + dps_interfaces: + type: list + primary_key: name + min_length: 1 + max_length: 1 + items: + type: dict + keys: + name: + type: str + description: '"Dps1" is currently the only supported interface.' + valid_values: + - Dps1 + description: + type: str + shutdown: + type: bool + mtu: + type: int + description: Maximum Transmission Unit in bytes. + convert_types: + - str + min: 68 + max: 65535 + ip_address: + type: str + description: IPv4 address/mask. + flow_tracker: + type: dict + keys: + sampled: + type: str + description: Sampled flow tracker name. + hardware: + type: str + description: Hardware flow tracker name, + tcp_mss_ceiling: + type: dict + keys: + ipv4: + type: int + description: Segment Size for IPv4. + min: 64 + max: 65495 + convert_types: + - str + ipv6: + type: int + description: Segment Size for IPv6. + min: 64 + max: 65475 + convert_types: + - str + direction: + type: str + valid_values: + - ingress + - egress + description: Optional direction ('ingress', 'egress') for tcp mss ceiling. + eos_cli: + type: str + description: Multiline String with EOS CLI rendered directly on the Dps + interface in the final EOS configuration. + dynamic_prefix_lists: + type: list + items: + type: dict + keys: + name: + type: str + description: Dynamic prefix-list name. + match_map: + type: str + description: Route-map name. + prefix_list: + type: dict + keys: + ipv4: + type: str + description: Prefix-list name. + ipv6: + type: str + description: Prefix-list name. + enable_password: + type: dict + keys: + disabled: + type: bool + description: Set to `true` to configure `no enable password` which is the + EOS default. + hash_algorithm: + type: str + valid_values: + - md5 + - sha512 + key: + type: str + description: 'Must be the hash of the password using the specified algorithm. + + By default EOS salts the password, so the simplest is to generate the hash + on an EOS device. + + ' + eos_cli: + type: str + description: Multiline string with EOS CLI rendered directly on the root level + of the final EOS configuration. + eos_cli_config_gen_configuration: + type: dict + documentation_options: + table: role-settings keys: + enable: + type: bool + description: Generate device EOS configurations. + default: true hide_passwords: type: bool description: 'Replace the input data using the `hide_passwords` filter in - the Jinja2 templates by '''' in the configuration if true + the Jinja2 templates by '''' in the configuration if true. ' default: false eos_cli_config_gen_documentation: type: dict + documentation_options: + table: role-settings keys: + enable: + type: bool + description: Generate device Markdown documentation. + default: true hide_passwords: type: bool description: 'Replace the input data using the `hide_passwords` filter in - the Jinja2 templates by '''' in the documentation if true + the Jinja2 templates by '''' in the documentation if true. ' default: true @@ -1104,7 +1954,7 @@ keys: type: int convert_types: - str - description: Interval in seconds + description: Interval in seconds. default: 300 min: 30 max: 86400 @@ -1126,42 +1976,71 @@ keys: max: 600 convert_types: - str - description: Interval in seconds for updating interface counters" + description: Interval in seconds for updating interface counters. speed: type: str - description: Speed can be interface_speed or forced interface_speed or auto - interface_speed + description: Speed should be set in the format `` or `forced + ` or `auto `. mtu: type: int + min: 68 + max: 65535 convert_types: - str l2_mtu: type: int + min: 68 + max: 65535 convert_types: - str description: '"l2_mtu" should only be defined for platforms supporting the - "l2 mtu" CLI + "l2 mtu" CLI. + + ' + l2_mru: + type: int + min: 68 + max: 65535 + convert_types: + - str + description: '"l2_mru" should only be defined for platforms supporting the + "l2 mru" CLI. ' vlans: type: str convert_types: - int - description: 'List of switchport vlans as string + description: 'List of switchport vlans as string. - For a trunk port this would be a range like "1-200,300" + For a trunk port this would be a range like "1-200,300". - For an access port this would be a single vlan "123" + For an access port this would be a single vlan "123". ' + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: ethernet_interfaces[].switchport.access_vlan or ethernet_interfaces[].switchport.trunk.allowed_vlan native_vlan: type: int convert_types: - str + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: ethernet_interfaces[].switchport.trunk.native_vlan native_vlan_tag: type: bool description: If setting both native_vlan and native_vlan_tag, native_vlan_tag - takes precedence + takes precedence. + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: ethernet_interfaces[].switchport.trunk.native_vlan_tag mode: type: str valid_values: @@ -1169,7 +2048,17 @@ keys: - dot1q-tunnel - trunk - trunk phone + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: ethernet_interfaces[].switchport.mode phone: + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: ethernet_interfaces[].switchport.phone type: dict keys: trunk: @@ -1179,12 +2068,22 @@ keys: - tagged phone - untagged - untagged phone + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: ethernet_interfaces[].switchport.phone.trunk vlan: type: int min: 1 max: 4094 convert_types: - str + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: ethernet_interfaces[].switchport.phone.vlan l2_protocol: type: dict keys: @@ -1192,16 +2091,25 @@ keys: type: int convert_types: - str - description: Vlan tag to configure on sub-interface + description: Vlan tag to configure on sub-interface. forwarding_profile: type: str - description: L2 protocol forwarding profile + description: L2 protocol forwarding profile. trunk_groups: type: list items: type: str + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: ethernet_interfaces[].switchport.trunk.groups type: type: str + deprecation: + warning: true + remove_in_version: 6.0.0 + url: https://avd.arista.com/stable/docs/release-notes/5.x.x.html#removal-of-type-key-dependency-for-rendering-ethernetport-channel-interfaces-configuration-and-documentation valid_values: - routed - switched @@ -1211,8 +2119,7 @@ keys: description: 'l3dot1q and l2dot1q are used for sub-interfaces. The parent interface should be defined as routed. - Interface will not be listed in device documentation, unless "type" is - set. + The `type = switched/routed` should not be combined with `switchport`. ' snmp_trap_link_change: @@ -1222,10 +2129,10 @@ keys: keys: ipv4: type: bool - description: Enable address locking for IPv4 + description: Enable address locking for IPv4. ipv6: type: bool - description: Enable address locking for IPv6 + description: Enable address locking for IPv6. flowcontrol: type: dict keys: @@ -1237,7 +2144,7 @@ keys: - 'off' vrf: type: str - description: VRF name + description: VRF name. convert_types: - int flow_tracker: @@ -1245,7 +2152,10 @@ keys: keys: sampled: type: str - description: Flow tracker name + description: Sampled flow tracker name. + hardware: + type: str + description: Hardware flow tracker name. error_correction_encoding: type: dict keys: @@ -1264,7 +2174,7 @@ keys: keys: name: type: str - description: Group name + description: Group name. direction: type: str valid_values: @@ -1275,7 +2185,7 @@ keys: keys: identifier: type: str - description: EVPN Ethernet Segment Identifier (Type 1 format) + description: EVPN Ethernet Segment Identifier (Type 1 format). redundancy: type: str valid_values: @@ -1295,10 +2205,10 @@ keys: max: 65535 convert_types: - str - description: Preference_value is only used when "algorithm" is "preference" + description: Preference_value is only used when "algorithm" is "preference". dont_preempt: type: bool - description: Dont_preempt is only used when "algorithm" is "preference" + description: Dont_preempt is only used when "algorithm" is "preference". hold_time: type: int convert_types: @@ -1324,64 +2234,198 @@ keys: - str route_target: type: str - description: EVPN Route Target for ESI with format xx:xx:xx:xx:xx:xx + description: EVPN Route Target for ESI with format xx:xx:xx:xx:xx:xx. encapsulation_dot1q_vlan: type: int convert_types: - str - description: VLAN tag to configure on sub-interface + description: VLAN tag to configure on sub-interface. + deprecation: + warning: true + remove_in_version: 6.0.0 + new_key: encapsulation_dot1q.vlan + encapsulation_dot1q: + description: 'Warning: `encapsulation_dot1q` should not be combined with + `ethernet_interfaces[].type: l3dot1q` or `ethernet_interfaces[].type: + l2dot1q`.' + type: dict + keys: + vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + required: true + description: VLAD ID. + inner_vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: Inner VLAN ID. This setting can only be applied to sub-interfaces + on EOS. encapsulation_vlan: type: dict + description: 'This setting can only be applied to sub-interfaces on EOS. + + Warning: `encapsulation_vlan` should not be combined with `ethernet_interfaces[].type: + l3dot1q` or `ethernet_interfaces[].type: l2dot1q`.' keys: client: type: dict keys: dot1q: + deprecation: + warning: true + remove_in_version: 6.0.0 type: dict keys: vlan: type: int convert_types: - str - description: Client VLAN ID + min: 1 + max: 4094 + description: Client VLAN ID. outer: type: int convert_types: - str - description: Client Outer VLAN ID + min: 1 + max: 4094 + description: Client Outer VLAN ID. inner: type: int convert_types: - str - description: Client Inner VLAN ID + description: Client Inner VLAN ID. unmatched: type: bool + deprecation: + warning: true + remove_in_version: 6.0.0 + encapsulation: + type: str + valid_values: + - dot1q + - dot1ad + - unmatched + - untagged + vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: 'Client VLAN ID. Not applicable for `encapsulation: + untagged` or `encapsulation: unmatched`.' + outer_vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: 'Client Outer VLAN ID. Not applicable for `encapsulation: + untagged` or `encapsulation: unmatched`.' + inner_vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: 'Client Inner VLAN ID. Not applicable for `encapsulation: + untagged` or `encapsulation: unmatched`.' + inner_encapsulation: + type: str + valid_values: + - dot1q + - dot1ad network: type: dict description: Network encapsulations are all optional and skipped if - using client unmatched + using client unmatched. keys: dot1q: + deprecation: + warning: true + remove_in_version: 6.0.0 type: dict keys: vlan: type: int convert_types: - str - description: Network VLAN ID + min: 1 + max: 4094 + description: Network VLAN ID. outer: type: int convert_types: - str - description: Network outer VLAN ID + min: 1 + max: 4094 + description: Network outer VLAN ID. inner: type: int convert_types: - str - description: Network inner VLAN ID + min: 1 + max: 4094 + description: Network inner VLAN ID. client: type: bool + deprecation: + warning: true + remove_in_version: 6.0.0 + encapsulation: + description: '`untagged` (no encapsulation) is applicable for `untagged` + client only. + + `client` and `client inner` (retain client encapsulation) is not + applicable for `untagged` client.' + type: str + valid_values: + - dot1q + - dot1ad + - client + - client inner + - untagged + vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: 'Network VLAN ID. Not applicable for `encapsulation: + untagged` or `encapsulation: client`.' + outer_vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: 'Network outer VLAN ID. Not applicable for `encapsulation: + untagged` or `encapsulation: client`.' + inner_vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: 'Network inner VLAN ID. Not applicable for `encapsulation: + untagged` or `encapsulation: client`.' + inner_encapsulation: + type: str + valid_values: + - dot1q + - dot1ad vlan_id: + description: 'This setting can only be applied to sub-interfaces on EOS. + + Warning: `vlan_id` should not be combined with `ethernet_interfaces[].type + == l2dot1q`.' type: int min: 1 max: 4094 @@ -1389,14 +2433,25 @@ keys: - str ip_address: type: str - description: IPv4 address/mask or "dhcp" + description: IPv4 address/mask or "dhcp". ip_address_secondaries: type: list items: type: str + ip_verify_unicast_source_reachable_via: + type: str + valid_values: + - any + - rx dhcp_client_accept_default_route: type: bool - description: Install default-route obtained via DHCP + description: Install default-route obtained via DHCP. + dhcp_server_ipv4: + type: bool + description: Enable IPv4 DHCP server. + dhcp_server_ipv6: + type: bool + description: Enable IPv6 DHCP server. ip_helpers: type: list primary_key: ip_helper @@ -1407,22 +2462,26 @@ keys: type: str source_interface: type: str - description: Source interface name + description: Source interface name. vrf: type: str - description: VRF name + description: VRF name. convert_types: - int ip_nat: type: dict $ref: eos_cli_config_gen#/$defs/interface_ip_nat + keys: + service_profile: + type: str + description: NAT interface profile. ipv6_enable: type: bool ipv6_address: type: str ipv6_address_link_local: type: str - description: Link local IPv6 address/mask + description: Link local IPv6 address/mask. ipv6_nd_ra_disabled: type: bool ipv6_nd_managed_config_flag: @@ -1439,12 +2498,12 @@ keys: type: str convert_types: - int - description: Infinite or lifetime in seconds + description: Infinite or lifetime in seconds. preferred_lifetime: type: str convert_types: - int - description: Infinite or lifetime in seconds + description: Infinite or lifetime in seconds. no_autoconfig_flag: type: bool ipv6_dhcp_relay_destinations: @@ -1455,7 +2514,7 @@ keys: keys: address: type: str - description: DHCP server's IPv6 address + description: DHCP server's IPv6 address. vrf: type: str convert_types: @@ -1463,37 +2522,37 @@ keys: local_interface: type: str description: Local interface to communicate with DHCP server - mutually - exclusive to source_address + exclusive to source_address. source_address: type: str description: Source IPv6 address to communicate with DHCP server - - mutually exclusive to local_interface + mutually exclusive to local_interface. link_address: type: str description: Override the default link address specified in the relayed - DHCP packet + DHCP packet. access_group_in: type: str - description: Access list name + description: Access list name. access_group_out: type: str - description: Access list name + description: Access list name. ipv6_access_group_in: type: str - description: IPv6 access list name + description: IPv6 access list name. ipv6_access_group_out: type: str - description: IPv6 access list name + description: IPv6 access list name. mac_access_group_in: type: str - description: MAC access list name + description: MAC access list name. mac_access_group_out: type: str - description: MAC access list name + description: MAC access list name. multicast: type: dict description: Boundaries can be either 1 ACL or a list of multicast IP address_range(s)/prefix - but not combination of both + but not combination of both. keys: ipv4: type: dict @@ -1505,7 +2564,7 @@ keys: keys: boundary: type: str - description: ACL name or multicast IP subnet + description: ACL name or multicast IP subnet. out: type: bool static: @@ -1520,7 +2579,7 @@ keys: keys: boundary: type: str - description: ACL name or multicast IP subnet + description: ACL name or multicast IP subnet. static: type: bool ospf_network_point_to_point: @@ -1541,7 +2600,7 @@ keys: - message-digest ospf_authentication_key: type: str - description: Encrypted password - only type 7 supported + description: Encrypted password - only type 7 supported. ospf_message_digest_keys: type: list primary_key: id @@ -1562,13 +2621,16 @@ keys: - sha512 key: type: str - description: Encrypted password - only type 7 supported + description: Encrypted password - only type 7 supported. pim: type: dict keys: ipv4: type: dict keys: + border_router: + type: bool + description: Configure PIM border router. EOS default is false. dr_priority: type: int convert_types: @@ -1577,11 +2639,59 @@ keys: max: 429467295 sparse_mode: type: bool + bfd: + type: bool + description: Set the default for whether Bidirectional Forwarding + Detection is enabled for PIM. + bidirectional: + type: bool + hello: + type: dict + keys: + count: + type: str + convert_types: + - int + - float + description: Number of missed hellos after which the neighbor + expires. Range <1.5-65535>. + interval: + type: int + convert_types: + - str + min: 1 + max: 65535 + description: PIM hello interval in seconds. mac_security: type: dict keys: profile: type: str + tcp_mss_ceiling: + type: dict + description: 'The TCP MSS clamping feature involves clamping the maximum + segment size (MSS) in the TCP header + + of TCP SYN packets if it exceeds the configured MSS ceiling limit for + the interface.' + keys: + ipv4_segment_size: + type: int + convert_types: + - str + min: 64 + max: 65475 + ipv6_segment_size: + type: int + convert_types: + - str + min: 64 + max: 65475 + direction: + type: str + valid_values: + - egress + - ingress channel_group: type: dict keys: @@ -1597,7 +2707,10 @@ keys: - passive isis_enable: type: str - description: ISIS instance + description: ISIS instance. + isis_bfd: + type: bool + description: Enable BFD for ISIS. isis_passive: type: bool isis_metric: @@ -1621,7 +2734,7 @@ keys: - md5 isis_authentication_key: type: str - description: Type-7 encrypted password + description: Type-7 encrypted password. poe: type: dict keys: @@ -1638,10 +2751,10 @@ keys: - medium - low description: Prioritize a port's power in the event that one of the - switch's power supplies loses power + switch's power supplies loses power. reboot: description: Set the PoE power behavior for a PoE port when the system - is rebooted + is rebooted. type: dict keys: action: @@ -1649,10 +2762,10 @@ keys: valid_values: - maintain - power-off - description: PoE action for interface + description: PoE action for interface. link_down: description: Set the PoE power behavior for a PoE port when the port - goes down + goes down. type: dict keys: action: @@ -1660,7 +2773,7 @@ keys: valid_values: - maintain - power-off - description: PoE action for interface + description: PoE action for interface. power_off_delay: type: int min: 1 @@ -1671,7 +2784,7 @@ keys: a link down event occurs. Default value is 5 seconds in EOS. shutdown: description: Set the PoE power behavior for a PoE port when the port - is admin down + is admin down. type: dict keys: action: @@ -1679,7 +2792,7 @@ keys: valid_values: - maintain - power-off - description: PoE action for interface + description: PoE action for interface. limit: type: dict description: Override the hardware-negotiated power limit using either @@ -1700,7 +2813,7 @@ keys: - float fixed: type: bool - description: Set to ignore hardware classification + description: Set to ignore hardware classification. negotiation_lldp: type: bool description: Disable to prevent port from negotiating power with powered @@ -1734,6 +2847,17 @@ keys: valid_values: - e2e - p2p + profile: + type: dict + keys: + g8275_1: + type: dict + keys: + destination_mac_address: + type: str + valid_values: + - forwardable + - non-forwardable sync_message: type: dict keys: @@ -1750,7 +2874,7 @@ keys: type: str convert_types: - int - description: VLAN can be 'all' or list of vlans as string + description: VLAN can be 'all' or list of vlans as string. transport: type: str valid_values: @@ -1759,7 +2883,7 @@ keys: - layer2 profile: type: str - description: Interface profile + description: Interface profile. storm_control: type: dict keys: @@ -1771,14 +2895,14 @@ keys: convert_types: - int - float - description: Configure maximum storm-control level + description: Configure maximum storm-control level. unit: type: str default: percent valid_values: - percent - pps - description: Optional field and is hardware dependent + description: Optional field and is hardware dependent. broadcast: type: dict keys: @@ -1787,14 +2911,14 @@ keys: convert_types: - int - float - description: Configure maximum storm-control level + description: Configure maximum storm-control level. unit: type: str default: percent valid_values: - percent - pps - description: Optional field and is hardware dependent + description: Optional field and is hardware dependent. multicast: type: dict keys: @@ -1803,14 +2927,14 @@ keys: convert_types: - int - float - description: Configure maximum storm-control level + description: Configure maximum storm-control level. unit: type: str default: percent valid_values: - percent - pps - description: Optional field and is hardware dependent + description: Optional field and is hardware dependent. unknown_unicast: type: dict keys: @@ -1819,14 +2943,14 @@ keys: convert_types: - int - float - description: Configure maximum storm-control level + description: Configure maximum storm-control level. unit: type: str default: percent valid_values: - percent - pps - description: Optional field and is hardware dependent + description: Optional field and is hardware dependent. logging: type: dict keys: @@ -1839,8 +2963,11 @@ keys: type: bool spanning_tree: type: bool - storm_control: + storm_control_discards: type: bool + description: 'Discards due to storm-control. + + ' lldp: type: dict keys: @@ -1852,15 +2979,30 @@ keys: type: int convert_types: - str - description: ZTP vlan number + description: ZTP vlan number. trunk_private_vlan_secondary: type: bool + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: ethernet_interfaces[].switchport.trunk.private_vlan_secondary pvlan_mapping: type: str convert_types: - int - description: List of vlans as string + description: List of vlans as string. + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: ethernet_interfaces[].switchport.pvlan_mapping vlan_translations: + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: ethernet_interfaces[].switchport.vlan_translations type: list items: type: dict @@ -1870,12 +3012,12 @@ keys: convert_types: - int description: List of vlans as string (only one vlan if direction is - "both") + "both"). to: type: int convert_types: - str - description: VLAN ID + description: VLAN ID. direction: type: str valid_values: @@ -1936,6 +3078,9 @@ keys: type: bool host_mode_common: type: bool + mac_based_access_list: + type: bool + description: Operate interface in per-mac access-list mode. timeout: type: dict keys: @@ -1955,7 +3100,7 @@ keys: type: str convert_types: - int - description: Value can be 60-4294967295 or 'server' + description: Value can be 60-4294967295 or 'server'. reauth_timeout_ignore: type: bool tx_period: @@ -1993,17 +3138,41 @@ keys: max: 65535 convert_types: - str + aaa: + type: dict + keys: + unresponsive: + type: dict + description: Configure AAA timeout options. + keys: + eap_response: + type: str + description: EAP response to send. EOS default is `success`. + valid_values: + - success + - disabled + action: + type: dict + $ref: eos_cli_config_gen#/keys/dot1x/keys/aaa/keys/unresponsive/keys/action + keys: + traffic_allow_access_list: + type: str + description: Name of standard access-list to apply when + AAA times out. + phone_action: + type: dict + $ref: eos_cli_config_gen#/keys/dot1x/keys/aaa/keys/unresponsive/keys/phone_action service_profile: type: str - description: QOS profile + description: QOS profile. shape: type: dict keys: rate: type: str - description: 'Rate in kbps, pps or percent + description: 'Rate in kbps, pps or percent. - Supported options are platform dependent + Supported options are platform dependent. Examples: @@ -2027,12 +3196,12 @@ keys: type: int convert_types: - str - description: DSCP value + description: DSCP value. cos: type: int convert_types: - str - description: COS value + description: COS value. spanning_tree_bpdufilter: type: str convert_types: @@ -2096,12 +3265,12 @@ keys: type: int convert_types: - str - description: Interval in milliseconds + description: Interval in milliseconds. min_rx: type: int convert_types: - str - description: Rate in milliseconds + description: Rate in milliseconds. multiplier: type: int min: 3 @@ -2116,14 +3285,14 @@ keys: keys: input: type: str - description: Policy Based Routing Policy-map name + description: Policy Based Routing Policy-map name. qos: type: dict keys: input: type: str required: true - description: Quality of Service Policy-map name + description: Quality of Service Policy-map name. mpls: type: dict keys: @@ -2159,12 +3328,24 @@ keys: transceiver: type: dict keys: + frequency: + type: str + convert_types: + - int + - float + description: Transceiver Laser Frequency in GHz (min 190000, max 200000). + frequency_unit: + type: str + required: false + valid_values: + - ghz + description: Unit of Transceiver Laser Frequency. media: type: dict keys: override: type: str - description: Transceiver type + description: Transceiver type. ip_proxy_arp: type: bool traffic_policy: @@ -2172,25 +3353,82 @@ keys: keys: input: type: str - description: Ingress traffic policy + description: Ingress traffic policy. output: type: str - description: Egress traffic policy + description: Egress traffic policy. bgp: type: dict keys: session_tracker: type: str - description: Name of session tracker + description: Name of session tracker. + ip_igmp_host_proxy: + type: dict + keys: + enabled: + type: bool + groups: + type: list + primary_key: group + items: + type: dict + keys: + group: + type: str + description: Multicast Address. + exclude: + type: list + primary_key: source + description: The same source must not be present both in `exclude` + and `include` list. + items: + type: dict + keys: + source: + type: str + include: + type: list + primary_key: source + description: The same source must not be present both in `exclude` + and `include` list. + items: + type: dict + keys: + source: + type: str + report_interval: + type: int + convert_types: + - str + min: 1 + max: 31744 + description: Time interval between unsolicited reports. + access_lists: + type: list + primary_key: name + description: Non-standard Access List name. + items: + type: dict + keys: + name: + type: str + version: + type: int + convert_types: + - str + min: 1 + max: 3 + description: IGMP version on IGMP host-proxy interface. peer: type: str - description: Key only used for documentation or validation purposes + description: Key only used for documentation or validation purposes. peer_interface: type: str - description: Key only used for documentation or validation purposes + description: Key only used for documentation or validation purposes. peer_type: type: str - description: Key only used for documentation or validation purposes + description: Key only used for documentation or validation purposes. sflow: type: dict keys: @@ -2203,9 +3441,21 @@ keys: type: bool unmodified_enable: type: bool + sync_e: + type: dict + keys: + enable: + type: bool + priority: + type: str + description: The priority is used to influence the reference clock selection. + The EOS default priority is 127. The priority can be configured to + any integer between 1-255, or set to `disabled`. + convert_types: + - int port_profile: type: str - description: Key only used for documentation or validation purposes + description: Key only used for documentation or validation purposes. uc_tx_queues: type: list primary_key: id @@ -2217,17 +3467,17 @@ keys: convert_types: - str required: true - description: TX-Queue ID + description: TX-Queue ID. random_detect: type: dict keys: ecn: - description: Explicit Congestion Notification + description: Explicit Congestion Notification. type: dict keys: count: type: bool - description: Enable counter for random-detect ECNs + description: Enable counter for random-detect ECNs. threshold: type: dict keys: @@ -2241,7 +3491,7 @@ keys: - mbytes - milliseconds description: Indicate the units to be used for the threshold - values + values. min: type: int required: true @@ -2249,7 +3499,7 @@ keys: max: 256000000 convert_types: - str - description: Set the random-detect ECN minimum-threshold + description: Set the random-detect ECN minimum-threshold. max: type: int required: true @@ -2257,21 +3507,21 @@ keys: - str min: 1 max: 256000000 - description: Set the random-detect ECN maximum-threshold + description: Set the random-detect ECN maximum-threshold. max_probability: type: int min: 1 max: 100 convert_types: - str - description: Set the random-detect ECN max-mark-probability + description: Set the random-detect ECN max-mark-probability. weight: type: int min: 0 max: 15 convert_types: - str - description: Set the random-detect ECN weight + description: Set the random-detect ECN weight. tx_queues: type: list primary_key: id @@ -2283,17 +3533,17 @@ keys: convert_types: - str required: true - description: TX-Queue ID + description: TX-Queue ID. random_detect: type: dict keys: ecn: - description: Explicit Congestion Notification + description: Explicit Congestion Notification. type: dict keys: count: type: bool - description: Enable counter for random-detect ECNs + description: Enable counter for random-detect ECNs. threshold: type: dict keys: @@ -2307,14 +3557,14 @@ keys: - mbytes - milliseconds description: Indicate the units to be used for the threshold - values + values. min: type: int min: 1 max: 256000000 convert_types: - str - description: Set the random-detect ECN minimum-threshold + description: Set the random-detect ECN minimum-threshold. max: type: int required: true @@ -2322,7 +3572,7 @@ keys: - str min: 1 max: 256000000 - description: Set the random-detect ECN maximum-threshold + description: Set the random-detect ECN maximum-threshold. max_probability: type: int required: true @@ -2330,18 +3580,473 @@ keys: max: 100 convert_types: - str - description: Set the random-detect ECN max-mark-probability + description: Set the random-detect ECN max-mark-probability. weight: type: int min: 0 max: 15 convert_types: - str - description: Set the random-detect ECN weight + description: Set the random-detect ECN weight. + vrrp_ids: + type: list + description: VRRP model. + primary_key: id + items: + type: dict + keys: + id: + type: int + convert_types: + - str + description: VRID. + priority_level: + type: int + convert_types: + - str + description: Instance priority. + min: 1 + max: 254 + advertisement: + type: dict + keys: + interval: + type: int + convert_types: + - str + description: Interval in seconds. + min: 1 + max: 255 + preempt: + type: dict + keys: + enabled: + type: bool + required: true + delay: + type: dict + keys: + minimum: + type: int + convert_types: + - str + description: Minimum preempt delay in seconds. + min: 0 + max: 3600 + reload: + type: int + convert_types: + - str + description: Reload preempt delay in seconds. + min: 0 + max: 3600 + timers: + type: dict + keys: + delay: + type: dict + keys: + reload: + type: int + description: Delay after reload in seconds. + convert_types: + - str + min: 0 + max: 3600 + tracked_object: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: Tracked object name. + decrement: + type: int + convert_types: + - str + min: 1 + max: 254 + description: Decrement VRRP priority by 1-254. + shutdown: + type: bool + ipv4: + type: dict + keys: + address: + type: str + required: true + description: Virtual IPv4 address. + version: + type: int + convert_types: + - str + valid_values: + - 2 + - 3 + ipv6: + type: dict + keys: + address: + type: str + required: true + description: Virtual IPv6 address. + validate_state: + type: bool + description: Set to false to disable interface validation by the `eos_validate_state` + role. + switchport: + type: dict + description: This should not be combined with `ethernet_interfaces[].type + = switched/routed`. + keys: + enabled: + type: bool + description: 'Warning: This should not be combined with `ethernet_interfaces[].type + = routed`.' + mode: + type: str + valid_values: + - access + - dot1q-tunnel + - trunk + - trunk phone + description: 'Warning: This should not be combined with `ethernet_interfaces[].mode`.' + access_vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: 'Set VLAN when interface is in access mode. + + Warning: This should not be combined with `ethernet_interfaces[].mode + = access/dot1q-tunnel` and `ethernet_interface[].vlans`.' + trunk: + type: dict + keys: + allowed_vlan: + type: str + convert_types: + - int + description: 'VLAN ID or range(s) of VLAN IDs. + + Warning: This should not be combined with `ethernet_interfaces[].mode + = trunk` and `ethernet_interface[].vlans`.' + native_vlan: + type: int + convert_types: + - str + description: 'Set native VLAN when interface is in trunking mode. + + Warning: This should not be combined with `ethernet_interfaces[].native_vlan`.' + min: 1 + max: 4094 + native_vlan_tag: + type: bool + description: 'If setting both native_vlan and native_vlan_tag, native_vlan_tag + takes precedence. + + Warning: This should not be combined with `ethernet_interfaces[].native_vlan_tag`.' + private_vlan_secondary: + type: bool + description: 'Enable secondary VLAN mapping for a private vlan. + + Warning: This should not be combined with `ethernet_ineterfaces[].trunk_private_vlan_secondary`.' + groups: + description: 'Warning: This should not be combined with `ethernet_ineterfaces[].trunk_groups`. + + ' + type: list + items: + type: str + convert_types: + - int + description: Trunk group name. + phone: + type: dict + description: 'Warning: This should not be combined with `ethernet_interfaces[].phone`.' + keys: + vlan: + type: int + min: 1 + max: 4094 + convert_types: + - str + description: 'Warning: This should not be combined with `ethernet_interfaces[].phone.vlan`.' + trunk: + type: str + description: 'Warning: This should not be combined with `ethernet_interfaces[].phone.trunk`.' + valid_values: + - tagged + - tagged phone + - untagged + - untagged phone + pvlan_mapping: + type: str + convert_types: + - int + description: 'Secondary VLAN IDs of the private VLAN mapping. + + Warning: This should not be combined with `ethernet_interfaces[].pvlan_mapping`.' + dot1q: + type: dict + keys: + ethertype: + type: int + convert_types: + - str + min: 1536 + max: 65535 + description: Ethertype/TPID (Tag Protocol IDentifier) for VLAN tagged + frames. + vlan_tag: + type: str + description: Allow/disallow VLAN tagged frames. + valid_values: + - disallowed + - required + source_interface: + type: str + description: 'tx: Allow bridged traffic to go out of the source interface. + + tx multicast: Allow multicast traffic only to go out of the source + interface.' + valid_values: + - tx + - tx multicast + vlan_translations: + description: 'VLAN Translation mappings. + + Warning: This should not be combined with `ethernet_interfaces[].vlan_translations`.' + type: dict + keys: + in_required: + type: bool + description: Drop the ingress traffic that do not match any VLAN + mapping. + out_required: + type: bool + description: Drop the egress traffic that do not match any VLAN + mapping. + direction_in: + type: list + description: Map ingress traffic only. + items: + type: dict + keys: + from: + type: str + convert_types: + - int + description: VLAN ID or range of VLAN IDs to map from. Range + 1-4094. + required: true + to: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: VLAN ID to map to. + required: true + dot1q_tunnel: + type: bool + inner_vlan_from: + type: int + min: 1 + max: 4094 + convert_types: + - str + description: Inner VLAN ID to map from. + direction_out: + type: list + description: Map egress traffic only. + items: + type: dict + keys: + from: + type: str + convert_types: + - int + description: VLAN ID or range of VLAN IDs to map from. Range + 1-4094. + required: true + to: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: VLAN ID to map to. + dot1q_tunnel_to: + type: str + convert_types: + - int + description: 'VLAN ID or range of VLAN IDs or "all". Range + 1-4094. + + This takes precedence over `to` and `inner_vlan_to`.' + inner_vlan_to: + type: int + min: 1 + max: 4094 + convert_types: + - str + description: Inner VLAN ID to map to. + direction_both: + type: list + description: Map both egress and ingress traffic. + items: + type: dict + keys: + from: + type: str + convert_types: + - int + description: VLAN ID or range of VLAN IDs to map from. Range + 1-4094. + required: true + to: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: VLAN ID to map to. + required: true + dot1q_tunnel: + type: bool + inner_vlan_from: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: Inner VLAN ID to map from. + network: + type: bool + description: 'Enable use of network-side VLAN ID. + + This setting can only be enabled when `inner_vlan_from` + is defined.' + vlan_forwarding_accept_all: + type: bool + backup_link: + type: dict + keys: + interface: + type: str + description: Backup interface. Example - Ethernet4, Vlan10 etc. + prefer_vlan: + type: str + convert_types: + - int + description: VLANs to carry on the backup interface (1-4094). + backup: + type: dict + description: The `backup_link` is required for this setting. + keys: + dest_macaddr: + type: str + format: mac + description: 'Destination MAC address for MAC move updates. + + The mac address should be multicast or broadcast. + + Example: 01:00:00:00:00:00' + initial_mac_move_delay: + type: int + convert_types: + - str + description: Initial MAC move delay in milliseconds. + min: 0 + max: 65535 + mac_move_burst: + type: int + convert_types: + - str + description: Size of MAC move bursts. + min: 0 + max: 65535 + mac_move_burst_interval: + type: int + convert_types: + - str + description: MAC move burst interval in milliseconds. + min: 0 + max: 65535 + preemption_delay: + type: int + convert_types: + - str + description: Preemption delay in milliseconds. + min: 0 + max: 65535 + port_security: + type: dict + keys: + enabled: + type: bool + mac_address_maximum: + type: dict + description: Maximum number of MAC addresses allowed on the interface. + keys: + disabled: + type: bool + description: Disable port level check for port security (only + in violation 'shutdown' mode). + limit: + type: int + convert_types: + - str + min: 1 + max: 1000 + description: MAC address limit. + violation: + type: dict + description: Configure violation mode (shutdown or protect), EOS + default is 'shutdown'. + keys: + mode: + type: str + valid_values: + - shutdown + - protect + description: Configure port security mode. + protect_log: + type: bool + description: Log new addresses seen after limit is reached in + protect mode. + vlan_default_mac_address_maximum: + type: int + convert_types: + - str + min: 0 + max: 1000 + description: Default maximum MAC addresses for all VLANs on this + interface. + vlans: + type: list + primary_key: range + items: + type: dict + keys: + range: + type: str + convert_types: + - int + description: "VLAN ID or range(s) of VLAN IDs, <1-4094>.\nExample:\n + \ - 3\n - 1,3\n - 1-10\n" + mac_address_maximum: + type: int + convert_types: + - str eos_cli: type: str description: Multiline EOS CLI rendered directly on the ethernet interface - in the final EOS configuration + in the final EOS configuration. event_handlers: type: list description: 'Gives the ability to monitor and react to Syslog messages. @@ -2359,23 +4064,27 @@ keys: keys: name: type: str - description: Event Handler Name - action_type: - type: str - valid_values: - - bash - - increment - - log - action: - type: str - description: 'Command to execute - - ' + description: Event Handler Name. + actions: + type: dict + description: 'Note: `bash_command` and `log` are mutually exclusive. `bash_command` + takes precedence over `log`.' + keys: + bash_command: + type: str + description: Define BASH command action. Command could be multiline + also. + log: + type: bool + description: Log a message when the event is triggered. + increment_device_health_metric: + type: str + description: Name of device-health metric. delay: type: int convert_types: - str - description: 'Event-handler delay in seconds + description: 'Event-handler delay in seconds. ' trigger: @@ -2384,24 +4093,231 @@ keys: ' valid_values: + - on-boot + - on-counters + - on-intf - on-logging + - on-maintenance - on-startup-config + - vm-tracer vm + trigger_on_counters: + type: dict + keys: + condition: + type: str + description: Set the logical expression to evaluate. + granularity_per_source: + type: bool + description: "Set the granularity of event counting for a wildcarded + condition.\nExample -\n condition ( Arad*.IptCrcErrCnt.delta > 100 + ) and ( Arad*.UcFifoFullDrop.delta > 100 )\n [* wildcard is used + here]" + poll_interval: + type: int + convert_types: + - str + min: 1 + max: 1000000 + description: Set the polling interval in seconds. + trigger_on_logging: + type: dict + keys: + poll_interval: + type: int + convert_types: + - str + min: 1 + max: 1000000 + description: Set the polling interval in seconds. + regex: + type: str + description: Regular expression to use for searching log messages. + trigger_on_intf: + type: dict + description: 'Trigger condition occurs on specified interface changes. + + Note: Any one of the `ip`, `ipv6` and `operstatus` key needs to be defined + along with the `interface`.' + keys: + interface: + type: str + required: true + description: "Interface name.\nExample - Ethernet4\n Loopback4-6\n + \ Port-channel4,7" + ip: + type: bool + description: Action is triggered upon changes to interface IP address + assignment. + ipv6: + type: bool + description: Action is triggered upon changes to interface ipv6 address + assignment. + operstatus: + type: bool + description: Action is triggered upon changes to interface operStatus. + trigger_on_maintenance: + description: Settings required for trigger 'on-maintenance'. + type: dict + keys: + operation: + type: str + required: true + valid_values: + - enter + - exit + bgp_peer: + description: 'Ipv4/Ipv6 address or peer group name. + + Trigger condition occurs on maintenance operation of specified BGP + peer.' + type: str + action: + type: str + required: true + description: Action for maintenance operation. + valid_values: + - after + - before + - all + - begin + - end + stage: + type: str + description: Action is triggered after/before specified stage. + valid_values: + - bgp + - linkdown + - mlag + - ratemon + vrf: + type: str + description: VRF name. VRF can be defined for "bgp_peer" only. + interface: + type: str + description: Trigger condition occurs on maintenance operation of specified + interface. + unit: + type: str + description: Name of unit. Trigger condition occurs on maintenance operation + of specified unit + asynchronous: + type: bool + default: false + description: 'Set the action to be non-blocking. + + ' + action_type: + type: str + valid_values: + - bash + - increment + - log + deprecation: + warning: true + removed: true + remove_in_version: 5.0.0 + new_key: event_handlers.actions + action: + type: str + description: 'Command to execute. + + ' + deprecation: + warning: true + removed: true + remove_in_version: 5.0.0 + new_key: event_handlers.actions.bash_command regex: type: str + deprecation: + warning: true + removed: true + remove_in_version: 5.0.0 + new_key: event_handlers.trigger_on_logging.regex description: 'Regular expression to use for searching log messages. Required - for on-logging trigger + for on-logging trigger. ' - asynchronous: - type: bool - default: false - description: Set the action to be non-blocking. event_monitor: type: dict keys: enabled: type: bool + flow_tracking: + type: dict + keys: + sampled: + type: dict + $ref: eos_cli_config_gen#/$defs/flow_tracking + keys: + encapsulation: + type: dict + keys: + ipv4_ipv6: + type: bool + mpls: + type: bool + sample: + type: int + convert_types: + - str + min: 1 + max: 4294967295 + hardware_offload: + type: dict + keys: + ipv4: + type: bool + description: Configure hardware offload for IPv4 traffic. + ipv6: + type: bool + description: Configure hardware offload for IPv6 traffic. + threshold_minimum: + type: int + convert_types: + - str + min: 1 + max: 4294967295 + description: Minimum number of samples. + trackers: + type: list + primary_key: name + items: + type: dict + keys: + table_size: + type: int + convert_types: + - str + min: 1 + max: 614400 + description: 'Maximum number of entries in flow table. + + ' + record_export: + type: dict + keys: + mpls: + type: bool + description: Export MPLS forwarding information. + hardware: + type: dict + $ref: eos_cli_config_gen#/$defs/flow_tracking + keys: + record: + type: dict + keys: + format_ipfix_standard_timestamps_counters: + type: bool + description: Enable software export of IPFIX data records. flow_trackings: + documentation_options: + table: flow-tracking + deprecation: + removed: true + warning: true + new_key: flow_tracking + remove_in_version: v5.0.0 type: list primary_key: type items: @@ -2411,7 +4327,7 @@ keys: type: str valid_values: - sampled - description: Flow Tracking Type - only 'sampled' supported for now + description: Flow Tracking Type - only 'sampled' supported for now. sample: type: int convert_types: @@ -2426,7 +4342,7 @@ keys: keys: name: type: str - description: Tracker Name + description: Tracker Name. record_export: type: dict keys: @@ -2436,17 +4352,17 @@ keys: - str min: 3000 max: 900000 - description: Flow record inactive export timeout in milliseconds + description: Flow record inactive export timeout in milliseconds. on_interval: type: int convert_types: - str min: 1000 max: 36000000 - description: Flow record export interval in milliseconds + description: Flow record export interval in milliseconds. mpls: type: bool - description: Export MPLS forwarding information + description: Export MPLS forwarding information. exporters: type: list primary_key: name @@ -2455,17 +4371,17 @@ keys: keys: name: type: str - description: Exporter Name + description: Exporter Name. collector: type: dict keys: host: type: str description: Collector IPv4 address or IPv6 address or fully - qualified domain name + qualified domain name. port: type: int - description: Collector Port Number + description: Collector Port Number. min: 1 max: 65535 convert_types: @@ -2479,14 +4395,14 @@ keys: - str local_interface: type: str - description: Local Source Interface + description: Local Source Interface. template_interval: type: int convert_types: - str min: 5000 max: 3600000 - description: Template interval in milliseconds + description: Template interval in milliseconds. table_size: type: int convert_types: @@ -2501,7 +4417,7 @@ keys: default: false generate_default_config: type: bool - default: true + default: false description: 'The `generate_default_config` knob allows to omit default EOS configuration. This can be useful when leveraging `eos_cli_config_gen` to generate configlets @@ -2514,7 +4430,8 @@ keys: - RANCID Content Type - - Hostname + - Hostname (even if `hostname` variable is not set. Then the hostname is picked + up from `inventory_hostname`) - Default configuration for `aaa` @@ -2522,10 +4439,23 @@ keys: - Transceiver qsfp default mode - - End of configuration delimiter' + - End of configuration delimiter + + ' + deprecation: + warning: true + remove_in_version: 6.0.0 + url: https://avd.arista.com/devel/docs/porting-guides/5.x.x.html#default-eos-configuration-is-no-longer-automatically-generated generate_device_documentation: type: bool + documentation_options: + table: role-settings default: true + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: eos_cli_config_gen_documentation.enable hardware: type: dict keys: @@ -2545,12 +4475,25 @@ keys: type: dict keys: speed_group: - type: int + type: str convert_types: - - str + - int serdes: type: str - description: Serdes speed like "10g" or "25g" + description: Serdes speed like "10g" or "25g". + port_groups: + type: list + primary_key: port_group + items: + type: dict + keys: + port_group: + type: str + convert_types: + - int + select: + type: str + description: Select Ports to activate hardware_counters: type: dict keys: @@ -2596,6 +4539,7 @@ keys: - qos dual-rate-policer - route - routed-port + - segment-security - subinterface - tapagg - traffic-class @@ -2606,6 +4550,7 @@ keys: - vni encap - vtep decap - vtep encap + required: true direction: type: str valid_values: @@ -2639,7 +4584,7 @@ keys: ' layer3: type: bool - description: 'Supported only for the ''ip'' feature + description: 'Supported only for the ''ip'' feature. ' vrf: @@ -2685,22 +4630,22 @@ keys: keys: name: type: str - description: Interface-Group name + description: Interface-Group name. interfaces: type: list items: type: str - description: Interface Name + description: Interface Name. bgp_maintenance_profiles: type: list items: type: str - description: Name of BGP Maintenance Profile + description: Name of BGP Maintenance Profile. interface_maintenance_profiles: type: list items: type: str - description: Name of Interface Maintenance Profile + description: Name of Interface Maintenance Profile. interface_profiles: type: list primary_key: name @@ -2709,15 +4654,17 @@ keys: keys: name: type: str - description: Interface-Profile Name + description: Interface-Profile Name. commands: type: list required: true items: type: str - description: 'EOS CLI interface command + description: 'EOS CLI interface command. + + Example: "switchport mode access" - Example: "switchport mode access"' + ' ip_access_lists: type: list primary_key: name @@ -2727,12 +4674,14 @@ keys: keys: name: type: str - description: Access-list Name + description: Access-list Name. + convert_types: + - int counters_per_entry: type: bool entries: type: list - description: ACL Entries + description: ACL Entries. items: type: dict keys: @@ -2740,16 +4689,12 @@ keys: type: int convert_types: - str - description: 'ACL entry sequence number. - - ' + description: ACL entry sequence number. remark: type: str description: 'Comment up to 100 characters. - If remark is defined, other keys in acl entry will be ignored. - - ' + If remark is defined, other keys in the ACL entry will be ignored.' action: type: str valid_values: @@ -2757,25 +4702,20 @@ keys: - deny description: 'ACL action. - Required for standard entry. - - ' + Required except for remarks.' protocol: type: str - description: 'ip, tcp, udp, icmp or other protocol name or number. - - Required for standard entry. + description: '"ip", "tcp", "udp", "icmp" or other protocol name or + number. - ' + Required except for remarks.' source: type: str - description: 'any, A.B.C.D/E or A.B.C.D. - - A.B.C.D without a mask means host. + description: '"any", "/" or "". - Required for standard entry. + "" without a mask means host. - ' + Required except for remarks.' source_ports_match: type: str valid_values: @@ -2794,13 +4734,11 @@ keys: description: TCP/UDP source port name or number. destination: type: str - description: 'any, A.B.C.D/E or A.B.C.D. - - A.B.C.D without a mask means host. + description: '"any", "/" or "". - Required for standard entry. + "" without a mask means host. - ' + Required except for remarks.' destination_ports_match: type: str valid_values: @@ -2821,7 +4759,7 @@ keys: type: list items: type: str - description: TCP Flag Name + description: TCP Flag Name. fragments: type: bool description: Match non-head fragment packets. @@ -2830,7 +4768,7 @@ keys: description: Log matches against this rule. ttl: type: int - description: TTL value + description: TTL value. convert_types: - str min: 0 @@ -2884,7 +4822,7 @@ keys: primary_key: name display_name: IP Community Lists description: 'Communities and regexp entries MUST not be configured in the same - community-list + community-list. ' items: @@ -2892,7 +4830,7 @@ keys: keys: name: type: str - description: IP Community-list Name + description: IP Community-list Name. entries: type: list required: true @@ -2930,15 +4868,61 @@ keys: ' regexp: type: str - description: 'Regular Expression + description: 'Regular Expression. + + If defined, a regex community-list will be configured. - If defined, a regex community-list will be configured' + ' ip_dhcp_relay: type: dict keys: + always_on: + type: bool + description: DhcpRelay Agent will be in always-on mode. + all_subnets: + type: bool + description: Allow forwarding requests with secondary IP addresses in the + gateway address "giaddr" field. information_option: type: bool - description: Insert Option-82 information + description: Insert Option-82 information. + ip_dhcp_snooping: + type: dict + keys: + enabled: + type: bool + bridging: + type: bool + information_option: + type: dict + keys: + enabled: + type: bool + description: Enable insertion of option-82 in DHCP request packets. + circuit_id_type: + type: str + convert_types: + - int + description: '"none" or <0 - 255>.' + circuit_id_format: + type: str + description: 'Required if `circuit_id_type` is set. + + - "%h:%p" Hostname and interface name + + - "%p:%v" Interface name and VLAN ID' + valid_values: + - '%h:%p' + - '%p:%v' + vlan: + type: str + convert_types: + - int + description: 'VLAN range as string. + + "< vlan_id >, < vlan_id >-< vlan_id >" + + Example: 15,16,17,18' ip_domain_lookup: type: dict keys: @@ -2950,7 +4934,7 @@ keys: keys: name: type: str - description: 'Source Interface + description: 'Source Interface. ' vrf: @@ -2966,7 +4950,7 @@ keys: keys: name: type: str - description: Community-list Name + description: Community-list Name. entries: type: list required: true @@ -2982,9 +4966,11 @@ keys: extcommunities: type: str required: true - description: 'Communities as string + description: 'Communities as string. + + Example: "65000:65000" - Example: "65000:65000"' + ' ip_extcommunity_lists_regexp: type: list primary_key: name @@ -2994,7 +4980,7 @@ keys: keys: name: type: str - description: Community-list Name + description: Community-list Name. entries: type: list required: true @@ -3010,7 +4996,19 @@ keys: regexp: type: str required: true - description: Regular Expression + description: Regular Expression. + ip_ftp_client_source_interfaces: + type: list + items: + type: dict + keys: + name: + type: str + required: true + description: Interface Name. + vrf: + type: str + description: VRF Name. ip_hardware: type: dict keys: @@ -3034,7 +5032,7 @@ keys: type: dict keys: name: - description: Interface Name + description: Interface Name. type: str vrf: type: str @@ -3071,7 +5069,7 @@ keys: type: bool address: type: str - description: IP Address + description: IP Address. query_interval: type: int convert_types: @@ -3112,7 +5110,7 @@ keys: type: int convert_types: - str - description: VLAN ID + description: VLAN ID. enabled: type: bool querier: @@ -3122,7 +5120,7 @@ keys: type: bool address: type: str - description: IP Address + description: IP Address. query_interval: type: int convert_types: @@ -3159,8 +5157,10 @@ keys: type: bool proxy: type: bool - description: Global proxy settings should be enabled before enabling - per-vlan + description: 'Global proxy settings should be enabled before enabling + per-vlan. + + ' ip_name_servers: type: list items: @@ -3168,14 +5168,14 @@ keys: keys: ip_address: type: str - description: IPv4 or IPv6 address for DNS server + description: IPv4 or IPv6 address for DNS server. vrf: - description: VRF Name + description: VRF Name. type: str convert_types: - int priority: - description: Priority value (lower is first) + description: Priority value (lower is first). type: int convert_types: - str @@ -3190,7 +5190,21 @@ keys: - str min: 1 max: 64 - description: Buffer size in MB + description: Buffer size in MB. + profiles: + type: list + primary_key: name + items: + type: dict + $ref: eos_cli_config_gen#/$defs/interface_ip_nat + keys: + name: + type: str + vrf: + type: str + convert_types: + - int + description: Specify VRF for NAT profile. pools: type: list primary_key: name @@ -3199,13 +5213,19 @@ keys: keys: name: type: str + type: + type: str + valid_values: + - ip-port + - port-only + default: ip-port prefix_length: type: int - required: true convert_types: - str min: 16 max: 32 + description: It is only used and required when `type` is `ip-port`. ranges: type: list items: @@ -3213,12 +5233,16 @@ keys: keys: first_ip: type: str - required: true - description: IPv4 address + description: 'IPv4 address. + + Required when `type` is `ip-port` and ignored otherwise.' last_ip: type: str - required: true - description: IPv4 address + description: 'IPv4 address. + + Required when `type` is `ip-port` and ignored otherwise. + + `first_ip` and `last_ip` ip addresses should lie in same subnet.' first_port: type: int convert_types: @@ -3231,6 +5255,9 @@ keys: - str min: 1 max: 65535 + description: 'Required when `first_port` is set. + + `last_port` must be greater than or equal to `first_port`.' utilization_log_threshold: type: int convert_types: @@ -3248,13 +5275,13 @@ keys: - str min: 60 max: 3600 - description: in seconds + description: In seconds. local_interface: type: str - description: EOS interface name + description: EOS interface name. peer_address: type: str - description: IPv4 address + description: IPv4 address. port_range: type: dict keys: @@ -3270,7 +5297,7 @@ keys: - str min: 1024 max: 65535 - description: '>= first_port' + description: '>= first_port.' split_disabled: type: bool shutdown: @@ -3296,7 +5323,7 @@ keys: - str min: 1 max: 99 - description: Used to render 'ip nat translation low-mark ' + description: Used to render 'ip nat translation low-mark '. host_percentage: type: int convert_types: @@ -3304,7 +5331,7 @@ keys: min: 1 max: 99 description: Used to render 'ip nat translation low-mark - host' + host'. max_entries: type: dict keys: @@ -3328,7 +5355,7 @@ keys: keys: ip: type: str - description: IPv4 address + description: IPv4 address. limit: type: int required: true @@ -3354,7 +5381,7 @@ keys: - str min: 0 max: 4294967295 - description: in seconds + description: In seconds. ip_radius_source_interfaces: type: list items: @@ -3362,10 +5389,10 @@ keys: keys: name: type: str - description: Interface Name + description: Interface Name. vrf: type: str - description: VRF Name + description: VRF Name. convert_types: - int ip_routing: @@ -3387,11 +5414,48 @@ keys: description: Policy name. local_id: type: str - description: 'Local IKE Identification. + description: 'Local IKE identification. Can be an IPv4 or an IPv6 address. - ' + If both `local_id` and `local_id_fqdn` are set, `local_id_fqdn` takes + precedence.' + local_id_fqdn: + type: str + description: 'Local FQDN or UFQDN IKE identification. + + If both `local_id` and `local_id_fqdn` are set, `local_id_fqdn` takes + precedence.' + ike_lifetime: + type: int + convert_types: + - str + min: 1 + max: 24 + description: IKE lifetime in hours. + encryption: + type: str + valid_values: + - 3des + - aes128 + - aes256 + description: IKE encryption algorithm. + dh_group: + type: int + convert_types: + - str + valid_values: + - 1 + - 2 + - 5 + - 14 + - 15 + - 16 + - 17 + - 20 + - 21 + - 24 + description: Diffie-Hellman group for the key exchange. sa_policies: type: list description: Security Association policies. @@ -3402,24 +5466,52 @@ keys: name: type: str description: Name of the SA policy. + sa_lifetime: + type: dict + keys: + value: + type: int + description: 'Lifetime value for this SA. + + Valid range depends on the unit. + + <1-24> Lifetime in hours ( default ) + + <1-4000000> Packet limit in thousands + + <1-6000> Byte limit in GB ( 1024 MB ) + + <1-6144000> Byte limit in MB ( 1024 KB )' + unit: + type: str + valid_values: + - gigabytes + - hours + - megabytes + - thousand-packets + default: hours esp: type: dict keys: integrity: type: str valid_values: - - 'null' + - disabled - sha1 - sha256 + - sha384 + - sha512 + - md5 encryption: type: str valid_values: - - 'null' + - disabled - aes128 - aes128gcm128 - aes128gcm64 - aes256 - - aes256gcm256 + - aes256gcm128 + - 3des pfs_dh_group: type: int convert_types: @@ -3483,7 +5575,7 @@ keys: max: 3600 action: type: str - description: 'Action to apply + description: 'Action to apply. * ''clear'': Delete all connections @@ -3504,19 +5596,31 @@ keys: valid_values: - transport - tunnel + flow_parallelization_encapsulation_udp: + type: bool + description: 'Enable flow parallelization. + + When enabled, multiple cores are used to parallelize the IPsec encryption + and decryption processing.' key_controller: type: dict keys: profile: type: str description: IPsec profile name to use. + hardware_encryption_disabled: + type: bool + default: false + description: 'Disable hardware encryption. + + An SFE restart is needed for this change to take effect.' ip_ssh_client_source_interfaces: type: list items: type: dict keys: name: - description: Interface Name + description: Interface Name. type: str vrf: type: str @@ -3531,15 +5635,39 @@ keys: keys: name: type: str - description: Interface name + description: Interface name. vrf: type: str display_name: VRF convert_types: - int + ip_telnet_client_source_interfaces: + type: list + items: + type: dict + keys: + name: + type: str + required: true + description: Interface Name. + vrf: + type: str + description: VRF Name. + ip_tftp_client_source_interfaces: + type: list + items: + type: dict + keys: + name: + type: str + required: true + description: Interface Name. + vrf: + type: str + description: VRF Name. ip_virtual_router_mac_address: type: str - description: MAC address (hh:hh:hh:hh:hh:hh) + description: MAC address (hh:hh:hh:hh:hh:hh). ipv6_access_lists: type: list primary_key: name @@ -3549,7 +5677,9 @@ keys: keys: name: type: str - description: IPv6 Access-list Name + description: IPv6 Access-list Name. + convert_types: + - int counters_per_entry: type: bool sequence_numbers: @@ -3561,15 +5691,41 @@ keys: keys: sequence: type: int - description: Sequence ID + description: Sequence ID. convert_types: - str action: type: str required: true - description: 'Action as string + description: 'Action as string. - Example: "deny ipv6 any any"' + Example: "deny ipv6 any any" + + ' + ipv6_dhcp_relay: + type: dict + keys: + always_on: + type: bool + description: DhcpRelay Agent will be in always-on mode, off by default. + all_subnets: + type: bool + description: Allow forwarding requests with additional IPv6 addresses in the + gateway address "giaddr" field. + option: + type: dict + description: Insert DHCP Option. + keys: + link_layer_address: + type: bool + description: Add Option 79 (Link Layer Address Option). + remote_id_format: + type: str + valid_values: + - '%m:%i' + - '%m:%p' + description: Add RemoteID option 37 in format MAC address and interface + ID (`%m:%i`) or MAC address and interface name (`%m:%p`). ipv6_hardware: type: dict keys: @@ -3585,9 +5741,52 @@ keys: profile: type: str description: Pre-defined profile 'internet' or user-defined profile - name + name. ipv6_icmp_redirect: type: bool + ipv6_neighbor: + type: dict + keys: + static_entries: + type: list + description: Static IPv6 neighbor entries. + items: + type: dict + keys: + ipv6_address: + type: str + required: true + description: IPv6 address of neighbor. + vrf: + type: str + interface: + type: str + required: true + description: Interface name. + mac_address: + type: str + required: true + description: MAC address of neighbor like 'aa:af:12:34:bc:bf' + pattern: ^([0-9a-f]{2}:){5}[0-9a-f]{2}$ + persistent: + type: dict + keys: + enabled: + type: bool + required: true + description: Restore the IPv6 neighbor cache after reboot. + refresh_delay: + type: int + description: 'Time to wait in seconds before refreshing the IPv6 neighbor + cache after reboot (EOS default 600). + + It will require setting the `enabled` key to true. + + ' + min: 600 + max: 3600 + convert_types: + - str ipv6_prefix_lists: type: list primary_key: name @@ -3596,7 +5795,7 @@ keys: keys: name: type: str - description: Prefix-list Name + description: Prefix-list Name. sequence_numbers: type: list required: true @@ -3606,15 +5805,17 @@ keys: keys: sequence: type: int - description: Sequence ID + description: Sequence ID. convert_types: - str action: type: str required: true - description: 'Action as string + description: 'Action as string. + + Example: "permit 1b11:3a00:22b0:0082::/64 eq 128" - Example: "permit 1b11:3a00:22b0:0082::/64 eq 128"' + ' ipv6_standard_access_lists: type: list primary_key: name @@ -3623,7 +5824,9 @@ keys: keys: name: type: str - description: Access-list Name + description: Access-list Name. + convert_types: + - int counters_per_entry: type: bool sequence_numbers: @@ -3635,15 +5838,17 @@ keys: keys: sequence: type: int - description: Sequence ID + description: Sequence ID. convert_types: - str action: type: str required: true - description: 'Action as string + description: 'Action as string. + + Example: "deny ipv6 any any" - Example: "deny ipv6 any any"' + ' ipv6_static_routes: type: list items: @@ -3655,15 +5860,15 @@ keys: - int destination_address_prefix: type: str - description: IPv6 Network/Mask + description: IPv6 Network/Mask. interface: type: str gateway: type: str - description: IPv6 Address + description: IPv6 Address. track_bfd: type: bool - description: Track next-hop using BFD + description: Track next-hop using BFD. distance: type: int convert_types: @@ -3678,7 +5883,7 @@ keys: max: 4294967295 name: type: str - description: Description + description: Description. metric: type: int convert_types: @@ -3687,6 +5892,10 @@ keys: max: 4294967295 ipv6_unicast_routing: type: bool + is_deployed: + description: Key only used for documentation or validation purposes. + type: bool + default: true l2_protocol: type: dict keys: @@ -3812,7 +6021,7 @@ keys: keys: default: type: int - description: Default load interval in seconds + description: Default load interval in seconds. convert_types: - str local_users: @@ -3822,7 +6031,7 @@ keys: type: dict keys: name: - description: Username + description: Username. type: str disabled: type: bool @@ -3844,12 +6053,12 @@ keys: role: type: str description: 'EOS RBAC Role to be assigned to the user such as "network-admin" - or "network-operator" + or "network-operator". ' sha512_password: type: str - description: 'SHA512 Hash of Password + description: 'SHA512 Hash of Password. Must be the hash of the password. By default EOS salts the password with the username, so the simplest is to generate the hash on an EOS device @@ -3864,9 +6073,11 @@ keys: ' ssh_key: type: str + secondary_ssh_key: + type: str shell: type: str - description: 'Specify shell for the user + description: 'Specify shell for the user. ' valid_values: @@ -3888,9 +6099,7 @@ keys: - alerts - emergencies - disabled - description: 'Console logging severity level - - ' + description: Console logging severity level. monitor: type: str valid_values: @@ -3903,9 +6112,7 @@ keys: - alerts - emergencies - disabled - description: 'Monitor logging severity level - - ' + description: Monitor logging severity level. buffered: type: dict keys: @@ -3927,9 +6134,10 @@ keys: - notifications - warnings - disabled - description: 'Buffer logging severity level - - ' + description: Buffer logging severity level. + repeat_messages: + type: bool + description: Summarize concurrent repeat messages. trap: type: str valid_values: @@ -3943,9 +6151,7 @@ keys: - system - warnings - disabled - description: 'Trap logging severity level - - ' + description: Trap logging severity level. synchronous: type: dict keys: @@ -3962,9 +6168,7 @@ keys: - notifications - warnings - disabled - description: 'Synchronous logging severity level - - ' + description: Synchronous logging severity level. default: critical format: type: dict @@ -3978,18 +6182,20 @@ keys: - traditional year - traditional timezone year - traditional year timezone - description: Timestamp format + description: Timestamp format. hostname: type: str valid_values: - fqdn - ipv4 - description: Hostname format + description: Hostname format in syslogs. For hostname _only_, remove the + line. (default EOS CLI behaviour). sequence_numbers: type: bool - description: 'Add sequence numbers to log messages - - ' + description: Add sequence numbers to log messages. + rfc5424: + type: bool + description: Forward logs in RFC5424 format. facility: type: str valid_values: @@ -4019,7 +6225,7 @@ keys: - uucp source_interface: type: str - description: Source Interface Name + description: Source Interface Name. vrfs: type: list primary_key: name @@ -4030,10 +6236,10 @@ keys: type: str convert_types: - int - description: VRF name + description: VRF name. source_interface: type: str - description: Source interface name + description: Source interface name. hosts: type: list primary_key: name @@ -4042,7 +6248,7 @@ keys: keys: name: type: str - description: Syslog server name + description: Syslog server name. protocol: type: str valid_values: @@ -4069,7 +6275,7 @@ keys: keys: name: type: str - description: Match list + description: Match list. action: type: str valid_values: @@ -4077,6 +6283,15 @@ keys: event: type: dict keys: + congestion_drops_interval: + type: int + convert_types: + - str + min: 1 + max: 65535 + description: Logging interval in seconds. + global_link_status: + type: bool storm_control: type: dict keys: @@ -4091,7 +6306,56 @@ keys: - str min: 10 max: 65535 - description: Logging interval in seconds + description: Logging interval in seconds. + level: + type: list + description: Configure logging severity. + primary_key: facility + items: + type: dict + keys: + facility: + type: str + severity: + type: str + convert_types: + - int + description: 'Severity of facility. Below are the supported severities. + + emergencies System is unusable (severity=0) + + alerts Immediate action needed (severity=1) + + critical Critical conditions (severity=2) + + errors Error conditions (severity=3) + + warnings Warning conditions (severity=4) + + notifications Normal but significant conditions (severity=5) + + informational Informational messages (severity=6) + + debugging Debugging messages (severity=7) + + <0-7> Severity level value' + valid_values: + - alerts + - critical + - debugging + - emergencies + - errors + - informational + - notifications + - warnings + - '0' + - '1' + - '2' + - '3' + - '4' + - '5' + - '6' + - '7' loopback_interfaces: type: list primary_key: name @@ -4100,29 +6364,29 @@ keys: keys: name: type: str - description: Loopback interface name e.g. "Loopback0" + description: Loopback interface name e.g. "Loopback0". description: type: str shutdown: type: bool vrf: type: str - description: VRF name + description: VRF name. convert_types: - int ip_address: type: str - description: IPv4_address/Mask + description: IPv4_address/Mask. ip_address_secondaries: type: list items: type: str - description: IPv4_address/Mask + description: IPv4_address/Mask. ipv6_enable: type: bool ipv6_address: type: str - description: IPv6_address/Mask + description: IPv6_address/Mask. ip_proxy_arp: type: bool ospf_area: @@ -4139,7 +6403,10 @@ keys: type: bool isis_enable: type: str - description: ISIS instance name + description: ISIS instance name. + isis_bfd: + type: bool + description: Enable BFD for ISIS. isis_passive: type: bool isis_metric: @@ -4162,7 +6429,7 @@ keys: eos_cli: type: str description: EOS CLI rendered directly on the loopback interface in the - final EOS configuration + final EOS configuration. mac_access_lists: type: list primary_key: name @@ -4171,7 +6438,9 @@ keys: keys: name: type: str - description: MAC Access-list Name + description: MAC Access-list Name. + convert_types: + - int counters_per_entry: type: bool entries: @@ -4190,7 +6459,7 @@ keys: keys: aging_time: type: int - description: Aging time in seconds + description: Aging time in seconds. convert_types: - str notification_host_flap: @@ -4219,7 +6488,6 @@ keys: keys: license: type: dict - required: true keys: license_name: type: str @@ -4229,7 +6497,6 @@ keys: required: true fips_restrictions: type: bool - required: true profiles: type: list primary_key: name @@ -4238,7 +6505,7 @@ keys: keys: name: type: str - description: Profile-Name + description: Profile-Name. cipher: type: str valid_values: @@ -4276,7 +6543,7 @@ keys: - str min: 30 max: 100000 - description: Rekey period in seconds + description: Rekey period in seconds. sci: type: bool l2_protocols: @@ -4300,23 +6567,37 @@ keys: valid_values: - bypass - bypass unauthorized + traffic_unprotected: + type: dict + keys: + action: + type: str + required: true + description: Allow/drop the transmit/receive of unprotected traffic. + valid_values: + - allow + - drop + allow_active_sak: + type: bool + description: Allow transmit/receive of encrypted traffic using operational + SAK and block otherwise. maintenance: type: dict display_name: Maintenance Mode keys: default_interface_profile: type: str - description: 'Name of default Interface Profile + description: 'Name of default Interface Profile. ' default_bgp_profile: type: str - description: 'Name of default BGP Profile + description: 'Name of default BGP Profile. ' default_unit_profile: type: str - description: 'Name of default Unit Profile + description: 'Name of default Unit Profile. ' interface_profiles: @@ -4334,14 +6615,14 @@ keys: type: int convert_types: - str - description: 'Load Interval in Seconds + description: 'Load Interval in Seconds. ' threshold: type: int convert_types: - str - description: 'Threshold in kbps + description: 'Threshold in kbps. ' shutdown: @@ -4351,7 +6632,7 @@ keys: type: int convert_types: - str - description: 'Max delay in seconds + description: 'Max delay in seconds. ' bgp_profiles: @@ -4362,13 +6643,13 @@ keys: keys: name: type: str - description: BGP Profile Name + description: BGP Profile Name. initiator: type: dict keys: route_map_inout: type: str - description: Route Map + description: Route Map. unit_profiles: type: list primary_key: name @@ -4377,7 +6658,7 @@ keys: keys: name: type: str - description: Unit Profile Name + description: Unit Profile Name. on_boot: type: dict keys: @@ -4387,7 +6668,7 @@ keys: - str min: 300 max: 3600 - description: 'On-boot in seconds + description: 'On-boot in seconds. ' units: @@ -4398,12 +6679,12 @@ keys: keys: name: type: str - description: Unit Name + description: Unit Name. quiesce: type: bool profile: type: str - description: 'Name of Unit Profile + description: 'Name of Unit Profile. ' groups: @@ -4413,14 +6694,16 @@ keys: type: list items: type: str - description: 'Name of BGP Group + description: 'Name of BGP Group. ' interface_groups: type: list items: type: str - description: Name of Interface Group + description: 'Name of Interface Group. + + ' management_accounts: type: dict keys: @@ -4445,13 +6728,13 @@ keys: keys: name: type: str - description: Transport name + description: Transport name. ssl_profile: type: str - description: SSL profile name + description: SSL profile name. vrf: type: str - description: VRF name is optional + description: VRF name is optional. convert_types: - int notification_timestamp: @@ -4474,7 +6757,17 @@ keys: ' ip_access_group: type: str - description: ACL name + description: ACL name. + port: + type: int + description: 'GNMI port. + + Make sure to update the control-plane ACL accordingly in order + for the service to be reachable by external applications. + + ' + convert_types: + - str grpc_tunnels: type: list primary_key: name @@ -4483,19 +6776,19 @@ keys: keys: name: type: str - description: Transport name + description: Transport name. shutdown: type: bool - description: Operational status of the gRPC tunnel + description: Operational status of the gRPC tunnel. tunnel_ssl_profile: type: str - description: Tunnel SSL profile name + description: Tunnel SSL profile name. gnmi_ssl_profile: type: str - description: gNMI SSL profile name + description: gNMI SSL profile name. vrf: type: str - description: VRF name + description: VRF name. convert_types: - int destination: @@ -4504,7 +6797,7 @@ keys: address: type: str required: true - description: IP address or hostname + description: IP address or hostname. port: type: int min: 1 @@ -4512,14 +6805,14 @@ keys: required: true convert_types: - str - description: TCP Port + description: TCP Port. local_interface: type: dict keys: name: type: str required: true - description: Interface name + description: Interface name. port: type: int min: 1 @@ -4527,13 +6820,13 @@ keys: required: true convert_types: - str - description: TCP Port + description: TCP Port. target: type: dict keys: use_serial_number: type: bool - description: Use serial number as the Target ID + description: Use serial number as the Target ID. target_ids: type: list description: 'Target IDs as a list. @@ -4544,34 +6837,17 @@ keys: enable_vrfs: type: list deprecation: + removed: true warning: true new_key: transport.grpc remove_in_version: 5.0.0 - primary_key: name - description: 'These should not be mixed with the new keys above. - - ' - items: - type: dict - keys: - name: - type: str - description: VRF name - convert_types: - - int - access_group: - type: str - description: Standard IPv4 ACL name octa: type: dict deprecation: warning: true + removed: true new_key: provider remove_in_version: 5.0.0 - description: 'These should not be mixed with the new keys above. - - Octa activates `eos-native` provider and it is the only provider currently - supported by EOS.' management_api_http: type: dict keys: @@ -4580,11 +6856,11 @@ keys: enable_https: type: bool https_ssl_profile: - description: SSL Profile Name + description: SSL Profile Name. type: str default_services: type: bool - description: 'Enable default services: capi-doc and tapagg' + description: 'Enable default services: capi-doc and tapagg.' enable_vrfs: type: list primary_key: name @@ -4592,25 +6868,25 @@ keys: type: dict keys: name: - description: VRF Name + description: VRF Name. type: str convert_types: - int access_group: - description: Standard IPv4 ACL name + description: Standard IPv4 ACL name. type: str ipv6_access_group: - description: Standard IPv6 ACL name + description: Standard IPv6 ACL name. type: str protocol_https_certificate: type: dict keys: certificate: type: str - description: Name of certificate; private key must also be specified + description: Name of certificate; private key must also be specified. private_key: type: str - description: Name of private key; certificate must also be specified + description: Name of private key; certificate must also be specified. management_api_models: type: dict keys: @@ -4652,13 +6928,13 @@ keys: type: list items: type: str - description: IP or hostname + description: IP or hostname. source_interface: type: str - description: Interface name + description: Interface name. vrf: type: str - description: VRF Name + description: VRF Name. convert_types: - int management_defaults: @@ -4680,51 +6956,81 @@ keys: keys: name: type: str - description: Management Interface Name + description: Management Interface Name. description: type: str shutdown: type: bool + speed: + type: str + description: Speed should be set in the format `` or `forced + ` or `auto `. mtu: type: int vrf: type: str - description: VRF Name + description: VRF Name. convert_types: - int ip_address: type: str - description: IPv4_address/Mask + description: IPv4_address/Mask. ipv6_enable: type: bool ipv6_address: type: str - description: IPv6_address/Mask + description: IPv6_address/Mask. type: type: str valid_values: - oob - inband default: oob - description: For documentation purposes only + description: For documentation purposes only. gateway: type: str - description: IPv4 address of default gateway in management VRF + description: IPv4 address of default gateway in management VRF. ipv6_gateway: type: str - description: IPv6 address of default gateway in management VRF + description: IPv6 address of default gateway in management VRF. mac_address: type: str - description: MAC address + description: MAC address. + lldp: + type: dict + keys: + transmit: + type: bool + receive: + type: bool + ztp_vlan: + type: int + convert_types: + - str + description: ZTP vlan number. eos_cli: type: str description: Multiline EOS CLI rendered directly on the management interface - in the final EOS configuration + in the final EOS configuration. management_security: type: dict keys: - entropy_source: - type: str + entropy_sources: + type: dict + description: Source of entropy. + keys: + hardware: + type: bool + description: Use a hardware based source. + haveged: + type: bool + description: Use the HAVEGE algorithm. + cpu_jitter: + type: bool + description: Use the Jitter RNG algorithm of a CPU based source. + hardware_exclusive: + type: bool + description: Only use entropy from the hardware source. password: type: dict keys: @@ -4803,7 +7109,7 @@ keys: type: str tls_versions: type: str - description: "List of allowed TLS versions as string\nExamples:\n - + description: "List of allowed TLS versions as string.\nExamples:\n - \"1.0\"\n - \"1.0 1.1\"\n" convert_types: - float @@ -4812,7 +7118,7 @@ keys: description: 'cipher_list syntax follows the openssl cipher strings format. - Colon (:) separated list of allowed ciphers as a string + Colon (:) separated list of allowed ciphers as a string. ' trust_certificate: @@ -4820,7 +7126,7 @@ keys: keys: certificates: type: list - description: "List of trust certificate names\nExamples:\n - test1.crt\n + description: "List of trust certificate names.\nExamples:\n - test1.crt\n \ - test2.crt\n" items: type: str @@ -4846,7 +7152,7 @@ keys: keys: certificates: type: list - description: "List of chain certificate names\nExamples:\n - chain1.crt\n + description: "List of chain certificate names.\nExamples:\n - chain1.crt\n \ - chain2.crt\n" items: type: str @@ -4864,9 +7170,137 @@ keys: type: str key: type: str + certificate_revocation_lists: + type: list + description: 'List of CRLs (Certificate Revocation List). + + If specified, one CRL needs to be provided for every certificate in + the chain, even if the revocation list in the CRL is empty. + + ' + items: + type: str + shared_secret_profiles: + type: list + primary_key: profile + items: + type: dict + keys: + profile: + type: str + secrets: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + secret: + type: str + required: true + secret_type: + type: str + default: '7' + valid_values: + - '0' + - '7' + - 8a + convert_types: + - int + receive_lifetime: + type: dict + required: true + keys: + infinite: + type: bool + start_date_time: + type: str + description: 'Start date and time of lifetime of the secret. + End date should be greater than start date. + + Formats supported: + + 1. mm/dd/yyyy hh:mm:ss + + 2. yyyy-mm-dd hh:mm:ss + + e.g 2024-12-20 10:00:00' + end_date_time: + type: str + description: 'End date and time of lifetime of the secret. + End date should be greater than start date. + + Formats supported: + + 1. mm/dd/yyyy hh:mm:ss + + 2. yyyy-mm-dd hh:mm:ss + + e.g 2024-12-20 10:00:00' + transmit_lifetime: + type: dict + required: true + keys: + infinite: + type: bool + start_date_time: + type: str + description: 'Start date and time of lifetime of the secret. + End date should be greater than start date. + + Formats supported: + + 1. mm/dd/yyyy hh:mm:ss + + 2. yyyy-mm-dd hh:mm:ss + + e.g 2024-12-20 10:00:00' + end_date_time: + type: str + description: 'End date and time of lifetime of the secret. + End date should be greater than start date. + + Formats supported: + + 1. mm/dd/yyyy hh:mm:ss + + 2. yyyy-mm-dd hh:mm:ss + + e.g 2024-12-20 10:00:00' + local_time: + type: bool + description: Configuring secret using the local timezone from + system clock. Default is UTC. + entropy_source: + type: str + deprecation: + warning: true + removed: true + remove_in_version: v5.0.0 + new_key: entropy_sources management_ssh: type: dict keys: + authentication: + type: dict + keys: + empty_passwords: + type: str + valid_values: + - auto + - deny + - permit + description: Permit or deny empty passwords for SSH authentication. + protocols: + type: list + items: + type: str + valid_values: + - keyboard-interactive + - password + - public-key + description: Allowed SSH authentication methods. access_groups: type: list items: @@ -4874,10 +7308,10 @@ keys: keys: name: type: str - description: Standard ACL Name + description: Standard ACL Name. vrf: type: str - description: VRF Name + description: VRF Name. convert_types: - int ipv6_access_groups: @@ -4887,10 +7321,10 @@ keys: keys: name: type: str - description: Standard ACL Name + description: Standard ACL Name. vrf: type: str - description: VRF Name + description: VRF Name. convert_types: - int idle_timeout: @@ -4899,32 +7333,41 @@ keys: - str min: 0 max: 86400 - description: Idle timeout in minutes + description: Idle timeout in minutes. cipher: - description: Cryptographic ciphers for SSH to use + description: Cryptographic ciphers for SSH to use. type: list items: type: str key_exchange: - description: Cryptographic key exchange methods for SSH to use + description: Cryptographic key exchange methods for SSH to use. type: list items: type: str mac: - description: Cryptographic MAC algorithms for SSH to use + description: Cryptographic MAC algorithms for SSH to use. type: list items: type: str + fips_restrictions: + type: bool + description: Use FIPS compliant algorithms. hostkey: type: dict keys: server: - description: SSH host key settings + description: SSH host key settings. type: list items: type: str + server_cert: + type: str + description: Configure switch's hostkey cert file. + client_strict_checking: + type: bool + description: Enforce strict host key checking. enable: - description: Enable SSH daemon + description: Enable SSH daemon. type: bool connection: type: dict @@ -4935,14 +7378,14 @@ keys: - str min: 1 max: 100 - description: Maximum total number of SSH sessions to device + description: Maximum total number of SSH sessions to device. per_host: type: int convert_types: - str min: 1 max: 20 - description: Maximum number of SSH sessions to device from a single host + description: Maximum number of SSH sessions to device from a single host. vrfs: type: list primary_key: name @@ -4951,15 +7394,33 @@ keys: keys: name: type: str - description: VRF Name + description: VRF Name. convert_types: - int enable: - description: Enable SSH in VRF + description: Enable SSH in VRF. type: bool log_level: type: str - description: SSH daemon log level + description: SSH daemon log level. + client_alive: + type: dict + keys: + count_max: + type: int + convert_types: + - str + min: 1 + max: 1000 + description: Number of keep-alive packets that can be sent without a response + before the connection is assumed dead. + interval: + type: int + convert_types: + - str + min: 1 + max: 1000 + description: Time period (in seconds) to send SSH keep-alive packets. management_tech_support: type: dict keys: @@ -4973,7 +7434,7 @@ keys: keys: command: type: str - description: Command to exclude from tech-support + description: Command to exclude from tech-support. type: type: str valid_values: @@ -4988,11 +7449,43 @@ keys: keys: command: type: str - description: Command to include in tech-support + description: Command to include in tech-support. match_list_input: type: dict display_name: Match Lists keys: + prefix_ipv4: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: Prefix-List Name. + prefixes: + type: list + required: true + min_length: 1 + description: List of IPv4 prefixes (with the subnet mask e.g. 192.0.2.0/24). + items: + type: str + prefix_ipv6: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: Prefix-List Name. + prefixes: + type: list + required: true + min_length: 1 + description: List of IPv6 prefixes (with the subnet mask e.g. 2001:db8:abcd:0013::/64). + items: + type: str string: type: list primary_key: name @@ -5001,7 +7494,7 @@ keys: keys: name: type: str - description: Match-list Name + description: Match-list Name. sequence_numbers: type: list required: true @@ -5009,32 +7502,342 @@ keys: items: type: dict keys: - sequence: - type: int - description: Sequence ID - convert_types: - - str - match_regex: - type: str - required: true - description: Regular Expression - mcs_client: - type: dict - keys: - shutdown: - type: bool - cvx_secondary: - type: dict - keys: - name: - type: str - shutdown: - type: bool - server_hosts: - type: list - items: - type: str - description: IP or hostname + sequence: + type: int + description: Sequence ID. + convert_types: + - str + match_regex: + type: str + required: true + description: Regular Expression. + mcs_client: + type: dict + keys: + shutdown: + type: bool + cvx_secondary: + type: dict + keys: + name: + type: str + shutdown: + type: bool + server_hosts: + type: list + items: + type: str + description: IP or hostname. + metadata: + type: dict + description: 'The data under `metadata` is used for documentation, validation + or integration purposes. + + It will not affect the generated EOS configuration.' + keys: + platform: + type: str + system_mac_address: + type: str + cv_tags: + type: dict + keys: + device_tags: + type: list + items: + type: dict + keys: + name: + type: str + required: true + value: + type: str + required: true + interface_tags: + type: list + items: + type: dict + keys: + interface: + type: str + required: true + tags: + type: list + items: + type: dict + keys: + name: + type: str + required: true + value: + type: str + required: true + cv_pathfinder: + type: dict + description: Metadata used for CV Pathfinder visualization on CloudVision. + keys: + role: + type: str + region: + type: str + zone: + type: str + site: + type: str + vtep_ip: + type: str + ssl_profile: + type: str + address: + type: str + pathfinders: + type: list + items: + type: dict + keys: + vtep_ip: + type: str + required: true + interfaces: + type: list + items: + type: dict + keys: + name: + type: str + carrier: + type: str + circuit_id: + type: str + pathgroup: + type: str + public_ip: + type: str + pathgroups: + type: list + items: + type: dict + keys: + name: + type: str + required: true + carriers: + type: list + items: + type: dict + keys: + name: + type: str + imported_carriers: + type: list + items: + type: dict + keys: + name: + type: str + regions: + type: list + items: + type: dict + keys: + id: + type: int + name: + type: str + zones: + type: list + items: + type: dict + keys: + id: + type: int + name: + type: str + sites: + type: list + items: + type: dict + keys: + id: + type: int + name: + type: str + location: + type: dict + keys: + address: + type: str + vrfs: + type: list + items: + type: dict + keys: + name: + type: str + vni: + type: int + avts: + type: list + items: + type: dict + keys: + constraints: + type: dict + keys: + jitter: + type: int + latency: + type: int + lossrate: + type: str + convert_types: + - float + hop_count: + type: str + description: + type: str + id: + type: int + name: + type: str + pathgroups: + type: list + items: + type: dict + keys: + name: + type: str + preference: + type: str + application_profiles: + type: list + items: + type: str + internet_exit_policies: + type: list + items: + type: dict + keys: + name: + type: str + required: true + type: + type: str + required: true + city: + type: str + required: true + country: + type: str + required: true + upload_bandwidth: + type: int + download_bandwidth: + type: int + firewall: + type: bool + required: true + ips_control: + type: bool + required: true + acceptable_use_policy: + type: bool + required: true + vpn_credentials: + type: list + required: true + items: + type: dict + keys: + fqdn: + type: str + required: true + vpn_type: + type: str + required: true + pre_shared_key: + type: str + required: true + tunnels: + type: list + required: true + items: + type: dict + keys: + name: + type: str + required: true + preference: + type: str + required: true + applications: + type: dict + keys: + profiles: + type: list + items: + type: dict + keys: + name: + type: str + builtin_applications: + type: list + items: + type: dict + keys: + name: + type: str + services: + type: list + items: + type: str + user_defined_applications: + type: list + items: + type: dict + keys: + name: + type: str + categories: + type: list + items: + type: dict + keys: + category: + type: str + services: + type: list + items: + type: str + transport_protocols: + type: list + items: + type: str + categories: + type: dict + keys: + builtin_applications: + type: list + items: + type: dict + keys: + name: + type: str + category: + type: str + services: + type: list + items: + type: str + user_defined_applications: + type: list + items: + type: dict + keys: + name: + type: str + category: + type: str mlag_configuration: type: dict display_name: Multi-Chassis Link Aggregation (MLAG) Configuration @@ -5043,58 +7846,58 @@ keys: type: str heartbeat_interval: type: int - description: Heartbeat interval in milliseconds + description: Heartbeat interval in milliseconds. convert_types: - str local_interface: - description: Local Interface Name + description: Local Interface Name. type: str peer_address: type: str - description: IPv4 Address + description: IPv4 or IPv6 Address. peer_address_heartbeat: type: dict keys: peer_ip: type: str - description: IPv4 Address + description: IPv4 or IPv6 Address. vrf: - description: VRF Name + description: VRF Name. type: str convert_types: - int dual_primary_detection_delay: type: int - description: Delay in seconds + description: Delay in seconds. min: 0 max: 86400 convert_types: - str dual_primary_recovery_delay_mlag: type: int - description: Delay in seconds + description: Delay in seconds. min: 0 max: 86400 convert_types: - str dual_primary_recovery_delay_non_mlag: type: int - description: Delay in seconds + description: Delay in seconds. min: 0 max: 86400 convert_types: - str peer_link: - description: Port-Channel interface name + description: Port-Channel interface name. type: str reload_delay_mlag: type: str - description: Delay in seconds <0-86400> or 'infinity' + description: Delay in seconds <0-86400> or 'infinity'. convert_types: - int reload_delay_non_mlag: type: str - description: Delay in seconds <0-86400> or 'infinity' + description: Delay in seconds <0-86400> or 'infinity'. convert_types: - int monitor_connectivity: @@ -5118,18 +7921,28 @@ keys: description: 'Interface range(s) should be of same type, Ethernet, Loopback, Management etc. - Multiple interface ranges can be specified separated by "," + Multiple interface ranges can be specified separated by ",". ' local_interfaces: type: str + address_only: + type: bool + description: 'When address-only is configured, the source IP of the packet + is set to the interface + + IP but the packet may exit the device via a different interface. + + When set to `false`, the probe uses the interface to exit the device.' + default: true hosts: type: list + primary_key: name items: type: dict keys: name: - description: Host Name + description: Host Name. type: str description: type: str @@ -5137,6 +7950,15 @@ keys: type: str local_interfaces: type: str + address_only: + type: bool + description: 'When address-only is configured, the source IP of the + packet is set to the interface + + IP but the packet may exit the device via a different interface. + + When set to `false`, the probe uses the interface to exit the device.' + default: true url: type: str vrfs: @@ -5146,7 +7968,7 @@ keys: type: dict keys: name: - description: VRF Name + description: VRF Name. type: str convert_types: - int @@ -5163,13 +7985,23 @@ keys: type: str local_interfaces: type: str + address_only: + type: bool + description: 'When address-only is configured, the source IP of the + packet is set to the interface + + IP but the packet may exit the device via a different interface. + + When set to `false`, the probe uses the interface to exit the device.' + default: true hosts: type: list + primary_key: name items: type: dict keys: name: - description: Host name + description: Host name. type: str description: type: str @@ -5177,8 +8009,54 @@ keys: type: str local_interfaces: type: str + address_only: + type: bool + description: 'When address-only is configured, the source IP of + the packet is set to the interface + + IP but the packet may exit the device via a different interface. + + When set to `false`, the probe uses the interface to exit the + device.' + default: true url: type: str + monitor_layer1: + type: dict + description: Enable SYSLOG messages on transceiver SMBus communication failures. + keys: + enabled: + type: bool + required: true + description: Enable monitor layer1. + logging_mac_fault: + type: bool + description: Enable MAC fault logging. + logging_transceiver: + type: dict + description: Configure transceiver monitoring logging. + keys: + dom: + type: bool + description: Enable transceiver Digital Optical Monitoring (DOM) logging. + communication: + type: bool + description: Enable transceiver SMBus fail and reset logging. + enabled: + type: bool + description: Some platforms support only the `logging transceiver` command. + `enabled` key configures this command. + monitor_session_default_encapsulation_gre: + documentation_options: + table: monitor-sessions + type: dict + keys: + payload: + type: str + description: Mirroring GRE payload type configuration commands. + valid_values: + - full-packet + - inner-packet monitor_sessions: type: list items: @@ -5187,7 +8065,7 @@ keys: name: type: str required: true - description: Session Name + description: Session Name. sources: type: list items: @@ -5195,7 +8073,7 @@ keys: keys: name: type: str - description: Interface name, range or comma separated list + description: Interface name, range or comma separated list. direction: type: str valid_values: @@ -5208,62 +8086,289 @@ keys: type: type: str valid_values: - - ip + - ip + - ipv6 + - mac + name: + description: ACL Name. + type: str + priority: + type: int + convert_types: + - str + destinations: + type: list + items: + type: str + description: '''cpu'' or interface name, range or comma separated list.' + encapsulation_gre_metadata_tx: + type: bool + header_remove_size: + type: int + description: Number of bytes to remove from header. + convert_types: + - str + access_group: + type: dict + keys: + type: + type: str + valid_values: + - ip + - ipv6 + - mac + name: + description: ACL Name. + type: str + rate_limit_per_ingress_chip: + type: str + description: "Ratelimit and unit as string.\nExamples:\n \"100000 bps\"\n + \ \"100 kbps\"\n \"10 mbps\"\n" + rate_limit_per_egress_chip: + type: str + description: "Ratelimit and unit as string.\nExamples:\n \"100000 bps\"\n + \ \"100 kbps\"\n \"10 mbps\"\n" + sample: + type: int + convert_types: + - str + truncate: + type: dict + keys: + enabled: + type: bool + size: + type: int + description: Size in bytes. + convert_types: + - str + monitor_telemetry_influx: + documentation_options: + table: monitor-telemetry + type: dict + keys: + vrf: + type: str + destinations: + type: list + primary_key: name + description: Configure telemetry output destinations. + items: + type: dict + keys: + name: + type: str + description: InfluxDB connection name. + database: + type: str + description: Set name of the database. + data_retention_policy: + type: str + url: + type: str + description: It only accepts http(s), udp and unix domain destination + URL. + pattern: (http(s)?|udp|unix)://.+ + username: + type: str + password: + type: str + password_type: + type: str + convert_types: + - int + valid_values: + - '0' + - '7' + - 8a + default: '7' + source_group_standard_disabled: + type: bool + description: Disable standard set of telemetry. + source_sockets: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: Label of the socket connection. + connection_limit: + type: int + min: 0 + max: 4294967295 + convert_types: + - str + url: + type: str + description: It only accepts http(s), udp and unix domain socket URL. + pattern: (http(s)?|udp|unix)://.+ + tags: + type: list + primary_key: name + description: Extra tags added to the telemetry output. + items: + type: dict + keys: + name: + type: str + description: Key of the global tag pair. + value: + type: str + required: true + description: Value of the global tag pair. + monitor_telemetry_postcard_policy: + documentation_options: + table: monitor-telemetry + type: dict + keys: + disabled: + type: bool + default: true + description: Enable or disable the postcard telemetry feature. + ingress: + type: dict + keys: + collection: + type: dict + description: Collector configuration. + keys: + source: + type: str + description: Source IP address of GRE tunnel. + destination: + type: str + description: Destination IP address of GRE tunnel. + version: + type: int + description: Postcard version. + valid_values: + - 1 + - 2 + convert_types: + - str + sample: + type: dict + description: Sampling parameters. + keys: + rate: + type: int + description: Sampling rate. `rate` is preferred when both `rate` and + `tcp_udp_checksum` are defined. + convert_types: + - str + valid_values: + - 16384 + - 32768 + - 65536 + tcp_udp_checksum: + type: dict + description: TCP/UDP parameters. + keys: + value: + type: int + description: TCP/UDP checksum or IP ID value. + min: 0 + max: 65535 + convert_types: + - str + mask: + type: str + description: 16 bit hexadecimal mask for TCP/UDP or IP ID with + at most 2 unset bits. + marker_vxlan: + type: dict + keys: + enabled: + type: bool + description: Enable vxlan marking using default bit 0. + header_word_zero_bit: + type: int + min: 1 + max: 31 + convert_types: + - str + profiles: + type: list + description: Postcard telemetry profiles. + primary_key: name + items: + type: dict + keys: + name: + type: str + description: Profile name. + ingress_sample_policy: + type: str + sample_policies: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + match_rules: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + type: + type: str + description: IP address version. + required: true + valid_values: + - ipv4 - ipv6 - - mac - name: - description: ACL Name + destination_prefix: type: str - priority: - type: int - convert_types: - - str - destinations: - type: list - items: - type: str - description: '''cpu'' or interface name, range or comma separated list' - encapsulation_gre_metadata_tx: - type: bool - header_remove_size: - type: int - description: Number of bytes to remove from header - convert_types: - - str - access_group: - type: dict - keys: - type: - type: str - valid_values: - - ip - - ipv6 - - mac - name: - description: ACL Name - type: str - rate_limit_per_ingress_chip: - type: str - description: "Ratelimit and unit as string.\nExamples:\n \"100000 bps\"\n - \ \"100 kbps\"\n \"10 mbps\"\n" - rate_limit_per_egress_chip: - type: str - description: "Ratelimit and unit as string.\nExamples:\n \"100000 bps\"\n - \ \"100 kbps\"\n \"10 mbps\"\n" - sample: - type: int - convert_types: - - str - truncate: - type: dict - keys: - enabled: - type: bool - size: - type: int - description: Size in bytes - convert_types: - - str + description: 'IPv4 Network/Mask or IPv6 Network/Mask. Host part + of prefix must be zero. + + eg. 10.3.3.0/24' + source_prefix: + type: str + description: 'IPv4 Network/Mask or IPv6 Network/Mask. Host part + of prefix must be zero. + + eg. 10.3.3.0/24' + protocols: + type: list + primary_key: protocol + items: + type: dict + keys: + protocol: + type: str + valid_values: + - tcp + - udp + source_ports: + type: list + description: "A list of port numbers or port range or port + name. Combination of port numbers or range and port name + is not supported on EOS. The port numbers should be in + range of 0-65535.\ne.g.\n [ \"12\", \"14-20\" ]\n [ + \"www\" ]" + items: + type: str + convert_types: + - int + destination_ports: + type: list + description: "A list of port numbers or port range or port + name. Combination of port numbers or range and port name + is not supported on EOS. The port numbers should be in + range of 0-65535.\ne.g.\n [ \"12\", \"14-20\", \"80\" + ]\n [ \"https\" ]" + items: + type: str + convert_types: + - int mpls: type: dict keys: @@ -5279,27 +8384,29 @@ keys: shutdown: type: bool transport_address_interface: - description: Interface Name + description: Interface Name. type: str + icmp: + description: Enables the LSRs to generate ICMP reply messages and deliver + them to the originating host. + type: dict + keys: + fragmentation_needed_tunneling: + type: bool + description: Enables the MPLS tunneling of MTU exceeded ICMP replies (fragmentation + needed, packet too big). + ttl_exceeded_tunneling: + type: bool + description: Enables the MPLS tunneling of TTL exceeded ICMP replies. name_server: + documentation_options: + table: ip-name-servers deprecation: + removed: true warning: true new_key: ip_name_servers remove_in_version: v5.0.0 type: dict - keys: - source: - type: dict - keys: - vrf: - description: VRF Name - type: str - convert_types: - - int - nodes: - type: list - items: - type: str ntp: type: dict keys: @@ -5308,10 +8415,10 @@ keys: keys: name: type: str - description: Source interface + description: Source interface. vrf: type: str - description: VRF name + description: VRF name. convert_types: - int servers: @@ -5321,7 +8428,7 @@ keys: keys: name: type: str - description: IP or hostname e.g., 2.2.2.55, ie.pool.ntp.org + description: IP or hostname e.g., 2.2.2.55, 2001:db8::55, ie.pool.ntp.org. burst: type: bool iburst: @@ -5334,21 +8441,21 @@ keys: - str local_interface: type: str - description: Source interface + description: Source interface. maxpoll: type: int min: 3 max: 17 convert_types: - str - description: Value of maxpoll between 3 - 17 (Logarithmic) + description: Value of maxpoll between 3 - 17 (Logarithmic). minpoll: type: int min: 3 max: 17 convert_types: - str - description: Value of minpoll between 3 - 17 (Logarithmic) + description: Value of minpoll between 3 - 17 (Logarithmic). preferred: type: bool version: @@ -5359,7 +8466,7 @@ keys: - str vrf: type: str - description: VRF name + description: VRF name. convert_types: - int authenticate: @@ -5378,7 +8485,7 @@ keys: max: 65534 convert_types: - str - description: Key identifier + description: Key identifier. hash_algorithm: type: str valid_values: @@ -5386,7 +8493,7 @@ keys: - sha1 key: type: str - description: Obfuscated key + description: Obfuscated key. key_type: type: str convert_types: @@ -5397,10 +8504,45 @@ keys: - 8a trusted_keys: type: str - description: List of trusted-keys as string ex. 10-12,15 + description: List of trusted-keys as string ex. 10-12,15. + convert_types: + - int patch_panel: type: dict keys: + connector: + type: dict + keys: + interface: + type: dict + keys: + patch: + type: dict + keys: + bgp_vpws_remote_failure_errdisable: + type: bool + recovery: + type: dict + keys: + review_delay: + type: dict + keys: + min: + type: int + required: true + min: 10 + max: 600 + convert_types: + - str + description: Minimum delay. + max: + type: int + required: true + min: 15 + max: 900 + convert_types: + - str + description: Maximum delay. patches: type: list primary_key: name @@ -5417,7 +8559,7 @@ keys: min_length: 2 max_length: 2 description: Must have exactly two connectors to a patch of which at - least one must be of type "interface" + least one must be of type "interface". items: type: dict keys: @@ -5455,7 +8597,7 @@ keys: keys: name: type: str - description: Peer-filter Name + description: Peer-filter Name. sequence_numbers: type: list required: true @@ -5465,17 +8607,20 @@ keys: keys: sequence: type: int - description: Sequence ID + description: Sequence ID. convert_types: - str match: type: str required: true - description: 'Match as string + description: 'Match as string. - Example: "as-range 1-100 result accept"' + Example: "as-range 1-100 result accept" + + ' platform: type: dict + description: Every key below this point is platform dependent. keys: trident: type: dict @@ -5556,8 +8701,8 @@ keys: required: true convert_types: - int - description: 'Drop Threshold. This value may also be - fractions. + description: 'Drop Threshold. This value may also + be fractions. Example: 7/8 or 3/4 or 1/2 @@ -5615,8 +8760,8 @@ keys: required: true convert_types: - int - description: 'Drop Threshold. This value may also be - fractions. + description: 'Drop Threshold. This value may also + be fractions. Example: 7/8 or 3/4 or 1/2 @@ -5624,7 +8769,7 @@ keys: sand: type: dict description: Most of the platform sand options are hardware dependent and - optional + optional. keys: qos_maps: type: list @@ -5660,6 +8805,28 @@ keys: valid_values: - ingress - egress + mdb_profile: + type: str + description: 'Sand platforms MDB Profile configuration. Note: l3-xxxl + does not support MLAG.' + valid_values: + - balanced + - balanced-xl + - l3 + - l3-xl + - l3-xxl + - l3-xxxl + sfe: + type: dict + description: Sfe (Software Forwarding Engine) settings. + keys: + data_plane_cpu_allocation_max: + type: int + description: Maximum number of CPUs used for data plane traffic forwarding. + convert_types: + - str + min: 1 + max: 128 poe: type: dict keys: @@ -5678,7 +8845,7 @@ keys: interface_shutdown: type: dict description: Set the global PoE power behavior for PoE ports when ports are - admin down + admin down. keys: action: type: str @@ -5692,14 +8859,14 @@ keys: keys: pbr: type: list - description: PBR Policy-Maps + description: PBR Policy-Maps. primary_key: name items: type: dict keys: name: type: str - description: Policy-Map Name + description: Policy-Map Name. classes: type: list primary_key: name @@ -5708,18 +8875,18 @@ keys: keys: name: type: str - description: Class Name + description: Class Name. index: type: int convert_types: - str drop: - description: '''drop'' and ''set'' are mutually exclusive' + description: '''drop'' and ''set'' are mutually exclusive.' type: bool set: description: 'Set Nexthop - ''drop'' and ''set'' are mutually exclusive + ''drop'' and ''set'' are mutually exclusive. ' type: dict @@ -5729,19 +8896,19 @@ keys: keys: ip_address: type: str - description: IPv4 or IPv6 Address + description: IPv4 or IPv6 Address. recursive: type: bool qos: type: list - description: QOS Policy-Maps + description: QOS Policy-Maps. primary_key: name items: type: dict keys: name: type: str - description: Policy-Map Name + description: Policy-Map Name. classes: type: list primary_key: name @@ -5750,7 +8917,7 @@ keys: keys: name: type: str - description: Class Name + description: Class Name. set: type: dict keys: @@ -5770,6 +8937,112 @@ keys: type: int convert_types: - str + police: + type: dict + keys: + rate: + type: int + convert_types: + - str + description: 'Specify rate. + + Range in kbps <8-200000000>.' + rate_unit: + type: str + valid_values: + - bps + - kbps + - mbps + - pps + default: bps + rate_burst_size: + type: int + convert_types: + - str + description: Range in bytes <256-128000000>. + rate_burst_size_unit: + type: str + valid_values: + - bytes + - kbytes + - mbytes + - packets + default: bytes + action: + type: dict + keys: + type: + description: Set action for policed traffic. + type: str + valid_values: + - dscp + - drop-precedence + dscp_value: + description: Set when action.type is set to "dscp". + type: str + convert_types: + - int + higher_rate: + type: int + convert_types: + - str + description: 'Specify higher rate. + + Range in kbps .' + higher_rate_unit: + type: str + valid_values: + - bps + - kbps + - mbps + - pps + default: bps + higher_rate_burst_size: + type: int + convert_types: + - str + description: Range in bytes <256-128000000>. + higher_rate_burst_size_unit: + type: str + valid_values: + - bytes + - kbytes + - mbytes + - packets + default: bytes + copp_system_policy: + type: dict + description: Control-plane policy configuration. + keys: + classes: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + shape: + type: int + description: Maximum rate limit. + min: 0 + max: 10000000 + convert_types: + - str + bandwidth: + type: int + description: Minimum bandwidth. + min: 0 + max: 10000000 + convert_types: + - str + rate_unit: + type: str + description: The `rate_unit` must be defined for `shape` and `bandwidth`. + valid_values: + - pps + - kbps port_channel_interfaces: type: list primary_key: name @@ -5788,31 +9061,57 @@ keys: keys: link_status: type: bool + storm_control_discards: + type: bool + description: 'Discards due to storm-control. + + ' shutdown: type: bool l2_mtu: type: int + min: 68 + max: 65535 convert_types: - str description: '"l2_mtu" should only be defined for platforms supporting the - "l2 mtu" CLI + "l2 mtu" CLI. + + ' + l2_mru: + type: int + min: 68 + max: 65535 + convert_types: + - str + description: '"l2_mru" should only be defined for platforms supporting the + "l2 mru" CLI. ' vlans: type: str convert_types: - int - description: 'List of switchport vlans as string + description: 'List of switchport vlans as string. - For a trunk port this would be a range like "1-200,300" + For a trunk port this would be a range like "1-200,300". - For an access port this would be a single vlan "123" + For an access port this would be a single vlan "123". ' + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: port_channel_interfaces[].switchport.access_vlan or port_channel_interfaces[].switchport.trunk.allowed_vlan snmp_trap_link_change: type: bool type: type: str + deprecation: + warning: true + remove_in_version: 6.0.0 + url: https://avd.arista.com/stable/docs/release-notes/5.x.x.html#removal-of-type-key-dependency-for-rendering-ethernetport-channel-interfaces-configuration-and-documentation valid_values: - routed - switched @@ -5827,66 +9126,200 @@ keys: ' encapsulation_dot1q_vlan: type: int - description: VLAN tag to configure on sub-interface convert_types: - str + description: VLAN tag to configure on sub-interface. + deprecation: + warning: true + remove_in_version: 6.0.0 + new_key: encapsulation_dot1q.vlan + encapsulation_dot1q: + description: 'Warning: `encapsulation_dot1q` should not be combined with + `ethernet_interfaces[].type: l3dot1q` or `ethernet_interfaces[].type: + l2dot1q`.' + type: dict + keys: + vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + required: true + description: VLAD ID. + inner_vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: Inner VLAN ID. This setting can only be applied to sub-interfaces + on EOS. vrf: type: str - description: VRF name + description: VRF name. convert_types: - int encapsulation_vlan: + description: 'This setting can only be applied to sub-interfaces on EOS. + + Warning: `encapsulation_vlan` should not be combined with `ethernet_interfaces[].type: + l3dot1q` or `ethernet_interfaces[].type: l2dot1q`.' type: dict keys: client: type: dict keys: dot1q: + deprecation: + warning: true + remove_in_version: 6.0.0 type: dict keys: vlan: type: int convert_types: - str - description: Client VLAN ID + description: Client VLAN ID. outer: type: int convert_types: - str - description: Client Outer VLAN ID + min: 1 + max: 4094 + description: Client Outer VLAN ID. inner: type: int convert_types: - str - description: Client Inner VLAN ID + min: 1 + max: 4094 + description: Client Inner VLAN ID. unmatched: type: bool + deprecation: + warning: true + remove_in_version: 6.0.0 + encapsulation: + type: str + valid_values: + - dot1q + - dot1ad + - unmatched + - untagged + vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: 'Client VLAN ID. Not applicable for `encapsulation: + untagged` or `encapsulation: unmatched`.' + outer_vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: 'Client Outer VLAN ID. Not applicable for `encapsulation: + untagged` or `encapsulation: unmatched`.' + inner_vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: 'Client Inner VLAN ID. Not applicable for `encapsulation: + untagged` or `encapsulation: unmatched`.' + inner_encapsulation: + type: str + valid_values: + - dot1q + - dot1ad network: type: dict description: Network encapsulation are all optional, and skipped if - using client unmatched + using client unmatched. keys: dot1q: + deprecation: + warning: true + remove_in_version: 6.0.0 type: dict keys: vlan: type: int convert_types: - str - description: Network VLAN ID + min: 1 + max: 4094 + description: Network VLAN ID. outer: type: int convert_types: - str - description: Network Outer VLAN ID + min: 1 + max: 4094 + description: Network Outer VLAN ID. inner: type: int convert_types: - str - description: Network Inner VLAN ID + min: 1 + max: 4094 + description: Network Inner VLAN ID. client: type: bool + deprecation: + warning: true + remove_in_version: 6.0.0 + encapsulation: + description: '`untagged` (no encapsulation) is applicable for `untagged` + client only. + + `client` and `client inner` (retain client encapsulation) is not + applicable for `untagged` client.' + type: str + valid_values: + - dot1q + - dot1ad + - client + - client inner + - untagged + vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: 'Network VLAN ID. Not applicable for `encapsulation: + untagged` or `encapsulation: client`.' + outer_vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: 'Network outer VLAN ID. Not applicable for `encapsulation: + untagged` or `encapsulation: client`.' + inner_vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: 'Network inner VLAN ID. Not applicable for `encapsulation: + untagged` or `encapsulation: client`.' + inner_encapsulation: + type: str + valid_values: + - dot1q + - dot1ad vlan_id: + description: 'This setting can only be applied to sub-interfaces on EOS. + + Warning: `vlan_id` should not be combined with `ethernet_interfaces[].type + == l2dot1q`.' type: int convert_types: - str @@ -5899,17 +9332,32 @@ keys: - dot1q-tunnel - trunk - trunk phone + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: port_channel_interfaces[].switchport.mode native_vlan: type: int convert_types: - str description: If setting both native_vlan and native_vlan_tag, native_vlan_tag - takes precedence + takes precedence. + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: port_channel_interfaces[].switchport.trunk.native_vlan native_vlan_tag: type: bool default: false description: If setting both native_vlan and native_vlan_tag, native_vlan_tag - takes precedence + takes precedence. + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: port_channel_interfaces[].switchport.trunk.native_vlan_tag link_tracking_groups: type: list primary_key: name @@ -5918,7 +9366,7 @@ keys: keys: name: type: str - description: Group name + description: Group name. direction: type: str valid_values: @@ -5926,18 +9374,33 @@ keys: - downstream phone: type: dict + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: port_channel_interfaces[].switchport.phone keys: trunk: type: str valid_values: - tagged - untagged + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: port_channel_interfaces[].switchport.phone.trunk vlan: type: int convert_types: - str min: 1 max: 4094 + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: port_channel_interfaces[].switchport.phone.vlan l2_protocol: type: dict keys: @@ -5945,31 +9408,37 @@ keys: type: int convert_types: - str - description: Vlan tag to configure on sub-interface + description: Vlan tag to configure on sub-interface. forwarding_profile: type: str - description: L2 protocol forwarding profile + description: L2 protocol forwarding profile. mtu: type: int + min: 68 + max: 65535 convert_types: - str mlag: type: int convert_types: - str - description: MLAG ID + description: MLAG ID. min: 1 max: 2000 trunk_groups: type: list items: type: str + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: port_channel_interfaces[].switchport.trunk.groups lacp_fallback_timeout: type: int - description: Timeout in seconds + description: Timeout in seconds. EOS default is 90 seconds. convert_types: - str - default: 90 min: 0 max: 300 lacp_fallback_mode: @@ -5990,12 +9459,12 @@ keys: type: int convert_types: - str - description: DSCP value + description: DSCP value. cos: type: int convert_types: - str - description: COS value + description: COS value. bfd: type: dict keys: @@ -6003,12 +9472,12 @@ keys: type: bool interval: type: int - description: Interval in milliseconds + description: Interval in milliseconds. convert_types: - str min_rx: type: int - description: Rate in milliseconds + description: Rate in milliseconds. convert_types: - str multiplier: @@ -6017,6 +9486,18 @@ keys: - str min: 3 max: 50 + neighbor: + type: str + description: IPv4 or IPv6 address. When the Port-channel is a L2 interface, + a local L3 BFD address (router_bfd.local_address) has to be defined + globally on the switch. + per_link: + type: dict + keys: + enabled: + type: bool + rfc_7130: + type: bool service_policy: type: dict keys: @@ -6025,14 +9506,14 @@ keys: keys: input: type: str - description: Policy Based Routing Policy-map name + description: Policy Based Routing Policy-map name. qos: type: dict keys: input: type: str required: true - description: Quality of Service Policy-map name + description: Quality of Service Policy-map name. mpls: type: dict keys: @@ -6047,12 +9528,27 @@ keys: type: bool trunk_private_vlan_secondary: type: bool + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: port_channel_interfaces[].switchport.trunk.private_vlan_secondary pvlan_mapping: type: str - description: List of vlans as string + description: List of vlans as string. convert_types: - int + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: port_channel_interfaces[].switchport.pvlan_mapping vlan_translations: + deprecation: + warning: true + removed: false + remove_in_version: 6.0.0 + new_key: port_channel_interfaces[].switchport.vlan_translations type: list items: type: dict @@ -6062,12 +9558,12 @@ keys: convert_types: - int description: List of vlans as string (only one vlan if direction is - "both") + "both"). to: type: int convert_types: - str - description: VLAN ID + description: VLAN ID. direction: type: str valid_values: @@ -6080,9 +9576,9 @@ keys: keys: rate: type: str - description: 'Rate in kbps, pps or percent + description: 'Rate in kbps, pps or percent. - Supported options are platform dependent + Supported options are platform dependent. Examples: @@ -6104,14 +9600,14 @@ keys: convert_types: - int - float - description: Configure maximum storm-control level + description: Configure maximum storm-control level. unit: type: str default: percent valid_values: - percent - pps - description: Optional field and is hardware dependent + description: Optional field and is hardware dependent. broadcast: type: dict keys: @@ -6120,14 +9616,14 @@ keys: convert_types: - int - float - description: Configure maximum storm-control level + description: Configure maximum storm-control level. unit: type: str default: percent valid_values: - percent - pps - description: Optional field and is hardware dependent + description: Optional field and is hardware dependent. multicast: type: dict keys: @@ -6136,14 +9632,14 @@ keys: convert_types: - int - float - description: Configure maximum storm-control level + description: Configure maximum storm-control level. unit: type: str default: percent valid_values: - percent - pps - description: Optional field and is hardware dependent + description: Optional field and is hardware dependent. unknown_unicast: type: dict keys: @@ -6152,19 +9648,22 @@ keys: convert_types: - int - float - description: Configure maximum storm-control level + description: Configure maximum storm-control level. unit: type: str default: percent valid_values: - percent - pps - description: Optional field and is hardware dependent + description: Optional field and is hardware dependent. ip_proxy_arp: type: bool isis_enable: type: str - description: ISIS instance + description: ISIS instance. + isis_bfd: + type: bool + description: Enable BFD for ISIS. isis_passive: type: bool isis_metric: @@ -6188,22 +9687,22 @@ keys: - md5 isis_authentication_key: type: str - description: Type-7 encrypted password + description: Type-7 encrypted password. traffic_policy: type: dict keys: input: type: str - description: Ingress traffic policy + description: Ingress traffic policy. output: type: str - description: Egress traffic policy + description: Egress traffic policy. evpn_ethernet_segment: type: dict keys: identifier: type: str - description: EVPN Ethernet Segment Identifier (Type 1 format) + description: EVPN Ethernet Segment Identifier (Type 1 format). redundancy: type: str valid_values: @@ -6223,10 +9722,10 @@ keys: max: 65535 convert_types: - str - description: Preference_value is only used when "algorithm" is "preference" + description: Preference_value is only used when "algorithm" is "preference". dont_preempt: type: bool - description: Dont_preempt is only used when "algorithm" is "preference" + description: Dont_preempt is only used when "algorithm" is "preference". default: false hold_time: type: int @@ -6253,34 +9752,10 @@ keys: - str route_target: type: str - description: EVPN Route Target for ESI with format xx:xx:xx:xx:xx:xx - esi: - type: str - description: 'EVPN Ethernet Segment Identifier (Type 1 format) - - If both "esi" and "evpn_ethernet_segment.identifier" are defined, the - new variable takes precedence - - ' - deprecation: - warning: true - new_key: evpn_ethernet_segment.identifier - remove_in_version: 5.0.0 - rt: - type: str - description: 'EVPN Route Target for ESI with format xx:xx:xx:xx:xx:xx - - If both "rt" and "evpn_ethernet_segment.route_target" are defined, the - new variable takes precedence - - ' - deprecation: - warning: true - new_key: evpn_ethernet_segment.route_target - remove_in_version: 5.0.0 + description: EVPN Route Target for ESI with format xx:xx:xx:xx:xx:xx. lacp_id: type: str - description: LACP ID with format xxxx.xxxx.xxxx + description: LACP ID with format xxxx.xxxx.xxxx. spanning_tree_bpdufilter: type: str convert_types: @@ -6341,6 +9816,17 @@ keys: valid_values: - e2e - p2p + profile: + type: dict + keys: + g8275_1: + type: dict + keys: + destination_mac_address: + type: str + valid_values: + - forwardable + - non-forwardable sync_message: type: dict keys: @@ -6357,16 +9843,31 @@ keys: type: str convert_types: - int - description: VLAN can be 'all' or list of vlans as string + description: VLAN can be 'all' or list of vlans as string. transport: type: str valid_values: - ipv4 - ipv6 - layer2 + mpass: + type: bool + description: 'When MPASS is enabled on an MLAG port-channel, MLAG peers + coordinate to function as a single PTP logical device. + + Arista PTP enabled devices always place PTP messages on the same physical + link within the port-channel. + + Hence, MPASS is needed only on MLAG port-channels connected to non-Arista + devices.' ip_address: type: str - description: IPv4 address/mask + description: IPv4 address/mask. + ip_verify_unicast_source_reachable_via: + type: str + valid_values: + - any + - rx ip_nat: type: dict $ref: eos_cli_config_gen#/$defs/interface_ip_nat @@ -6374,10 +9875,10 @@ keys: type: bool ipv6_address: type: str - description: IPv6 address/mask + description: IPv6 address/mask. ipv6_address_link_local: type: str - description: Link local IPv6 address/mask + description: Link local IPv6 address/mask. ipv6_nd_ra_disabled: type: bool ipv6_nd_managed_config_flag: @@ -6394,38 +9895,41 @@ keys: type: str convert_types: - int - description: Infinite or lifetime in seconds + description: Infinite or lifetime in seconds. preferred_lifetime: type: str convert_types: - int - description: Infinite or lifetime in seconds + description: Infinite or lifetime in seconds. no_autoconfig_flag: type: bool access_group_in: type: str - description: Access list name + description: Access list name. access_group_out: type: str - description: Access list name + description: Access list name. ipv6_access_group_in: type: str - description: IPv6 access list name + description: IPv6 access list name. ipv6_access_group_out: type: str - description: IPv6 access list name + description: IPv6 access list name. mac_access_group_in: type: str - description: MAC access list name + description: MAC access list name. mac_access_group_out: type: str - description: MAC access list name + description: MAC access list name. pim: type: dict keys: ipv4: type: dict keys: + border_router: + type: bool + description: Configure PIM border router. EOS default is false. dr_priority: type: int convert_types: @@ -6434,9 +9938,32 @@ keys: max: 429467295 sparse_mode: type: bool + bfd: + type: bool + description: Set the default for whether Bidirectional Forwarding + Detection is enabled for PIM. + bidirectional: + type: bool + hello: + type: dict + keys: + count: + type: str + convert_types: + - int + - float + description: Number of missed hellos after which the neighbor + expires. Range <1.5-65535>. + interval: + type: int + convert_types: + - str + min: 1 + max: 65535 + description: PIM hello interval in seconds. service_profile: type: str - description: QOS profile + description: QOS profile. ospf_network_point_to_point: type: bool ospf_area: @@ -6455,7 +9982,7 @@ keys: - message-digest ospf_authentication_key: type: str - description: Encrypted password + description: Encrypted password. ospf_message_digest_keys: type: list primary_key: id @@ -6476,28 +10003,88 @@ keys: - sha512 key: type: str - description: Encrypted password + description: Encrypted password. flow_tracker: type: dict keys: sampled: type: str - description: Flow tracker name + description: Sampled flow tracker name. + hardware: + type: str + description: Hardware flow tracker name. bgp: type: dict keys: session_tracker: type: str - description: Name of session tracker + description: Name of session tracker. + ip_igmp_host_proxy: + type: dict + keys: + enabled: + type: bool + groups: + type: list + primary_key: group + items: + type: dict + keys: + group: + type: str + description: Multicast Address. + exclude: + type: list + primary_key: source + description: The same source must not be present both in `exclude` + and `include` list. + items: + type: dict + keys: + source: + type: str + include: + type: list + primary_key: source + description: The same source must not be present both in `exclude` + and `include` list. + items: + type: dict + keys: + source: + type: str + report_interval: + type: int + convert_types: + - str + min: 1 + max: 31744 + description: Time interval between unsolicited reports. + access_lists: + type: list + primary_key: name + description: Non-standard Access List name. + items: + type: dict + keys: + name: + type: str + version: + type: int + convert_types: + - str + min: 1 + max: 3 + description: IGMP version on IGMP host-proxy interface. peer: type: str - description: Key only used for documentation or validation purposes + description: Key only used for documentation or validation purposes. peer_interface: type: str - description: Key only used for documentation or validation purposes + description: Key only used for documentation or validation purposes. peer_type: type: str - description: Key only used for documentation or validation purposes + description: Key only used for documentation or validation purposes. sflow: type: dict keys: @@ -6506,14 +10093,380 @@ keys: egress: type: dict keys: - enable: - type: bool - unmodified_enable: + enable: + type: bool + unmodified_enable: + type: bool + switchport: + type: dict + keys: + enabled: + type: bool + description: 'Warning: This should not be combined with `port_channel_interfaces[].type + = routed`.' + mode: + type: str + valid_values: + - access + - dot1q-tunnel + - trunk + - trunk phone + description: 'Warning: This should not be combined with `port_channel_interfaces[].mode`' + access_vlan: + type: int + convert_types: + - str + min: 1 + max: 4094 + description: 'Set VLAN when interface is in access mode. + + Warning: This should not be combined with `port_channel_interfaces[].mode + = access/dot1q-tunnel` and `port_channel_interface.vlans`.' + trunk: + type: dict + keys: + allowed_vlan: + type: str + convert_types: + - int + description: 'VLAN ID or range(s) of VLAN IDs (1-4094). + + Warning: This should not be combined with `port_channel_interfaces[].mode + = trunk` and `port_channel_interfaces[].vlans`.' + native_vlan: + type: int + convert_types: + - str + description: 'Set native VLAN when interface is in trunking mode. + + Warning: This should not be combined with `port_channel_interfaces[].native_vlan`.' + min: 1 + max: 4094 + native_vlan_tag: + type: bool + description: 'If setting both native_vlan and native_vlan_tag, native_vlan_tag + takes precedence. + + Warning: This should not be combined with `port_channel_interfaces[].native_vlan_tag`.' + private_vlan_secondary: + type: bool + description: 'Enable secondary VLAN mapping for a private vlan. + + Warning: This should not be combined with `port_channel_interfaces[].trunk_private_vlan_secondary`.' + groups: + description: 'Warning: This should not be combined with `port_channel_interfaces[].trunk_groups`. + + ' + type: list + items: + type: str + convert_types: + - int + description: Trunk group name. + phone: + type: dict + keys: + vlan: + type: int + min: 1 + max: 4094 + convert_types: + - str + description: 'Warning: This should not be combined with `port_channel_interfaces[].phone.vlan`.' + trunk: + type: str + description: 'Warning: This should not be combined with `port_channel_interfaces[].phone.trunk`' + valid_values: + - tagged + - tagged phone + - untagged + - untagged phone + pvlan_mapping: + type: str + convert_types: + - int + description: 'Secondary VLAN IDs of the private VLAN mapping. + + Warning: This should not be combined with `port_channel_interfaces[].pvlan_mapping`.' + dot1q: + type: dict + keys: + ethertype: + type: int + convert_types: + - str + min: 1536 + max: 65535 + description: Ethertype/TPID (Tag Protocol IDentifier) for VLAN tagged + frames. + vlan_tag: + type: str + valid_values: + - disallowed + - required + source_interface: + type: str + description: 'tx: Allow bridged traffic to go out of the source interface. + + tx multicast: Allow multicast traffic only to go out of the source + interface.' + valid_values: + - tx + - tx multicast + vlan_translations: + description: 'VLAN Translation mappings. + + Warning: This should not be combined with `port_channel_interfaces[].vlan_translations`.' + type: dict + keys: + in_required: + type: bool + description: Drop the ingress traffic that do not match any VLAN + mapping. + out_required: + type: bool + description: Drop the egress traffic that do not match any VLAN + mapping. + direction_in: + type: list + description: Map ingress traffic only. + items: + type: dict + keys: + from: + type: str + convert_types: + - int + description: VLAN ID or range of VLAN IDs to map from. Range + 1-4094. + to: + type: int + min: 1 + max: 4094 + convert_types: + - str + description: VLAN ID to map to. + dot1q_tunnel: + type: bool + inner_vlan_from: + type: int + min: 1 + max: 4094 + convert_types: + - str + description: Inner VLAN ID to map from. + direction_out: + type: list + description: Map egress traffic only. + items: + type: dict + keys: + from: + type: str + convert_types: + - int + description: VLAN ID or range of VLAN IDs to map from. Range + 1-4094. + required: true + to: + type: int + min: 1 + max: 4094 + convert_types: + - str + description: VLAN ID to map to. + dot1q_tunnel_to: + type: str + convert_types: + - int + description: 'VLAN ID or range of VLAN IDs or "all". Range + 1-4094. + + This takes precedence over `to` and `inner_vlan_to`.' + inner_vlan_to: + type: int + min: 1 + max: 4094 + convert_types: + - str + description: Inner VLAN ID to map to. + direction_both: + type: list + description: Map both egress and ingress traffic. + items: + type: dict + keys: + from: + type: str + convert_types: + - int + description: VLAN ID or range of VLAN IDs to map from. Range + 1-4094. + required: true + to: + type: int + min: 1 + max: 4094 + convert_types: + - str + description: VLAN ID to map to. + required: true + dot1q_tunnel: + type: bool + inner_vlan_from: + type: int + min: 1 + max: 4094 + convert_types: + - str + description: Inner VLAN ID to map from. + network: + type: bool + description: 'Enable use of network-side VLAN ID. + + This setting can only be enabled when `inner_vlan_from` + is defined.' + vlan_forwarding_accept_all: + type: bool + backup_link: + type: dict + keys: + interface: + type: str + required: true + description: Backup interface. Example - Ethernet4, Vlan10 etc. + prefer_vlan: + type: str + convert_types: + - int + description: VLANs to carry on the backup interface (1-4094). + backup: + type: dict + description: The `backup_link` is required for this setting. + keys: + dest_macaddr: + type: str + format: mac + description: 'Destination MAC address for MAC move updates. + + The mac address should be multicast or broadcast. + + Example: 01:00:00:00:00:00' + initial_mac_move_delay: + type: int + convert_types: + - str + description: Initial MAC move delay in milliseconds. + min: 0 + max: 65535 + mac_move_burst: + type: int + convert_types: + - str + description: Size of MAC move bursts. + min: 0 + max: 65535 + mac_move_burst_interval: + type: int + convert_types: + - str + description: MAC move burst interval in milliseconds. + min: 0 + max: 65535 + preemption_delay: + type: int + convert_types: + - str + description: Preemption delay in milliseconds. + min: 0 + max: 65535 + port_security: + type: dict + keys: + enabled: type: bool + mac_address_maximum: + type: dict + description: Maximum number of MAC addresses allowed on the interface. + keys: + disabled: + type: bool + description: Disable port level check for port security (only + in violation 'shutdown' mode). + limit: + type: int + convert_types: + - str + min: 1 + max: 1000 + description: MAC address limit. + violation: + type: dict + description: Configure violation mode (shutdown or protect), EOS + default is 'shutdown'. + keys: + mode: + type: str + valid_values: + - shutdown + - protect + description: Configure port security mode. + protect_log: + type: bool + description: Log new addresses seen after limit is reached in + protect mode. + vlan_default_mac_address_maximum: + type: int + convert_types: + - str + min: 0 + max: 1000 + description: Default maximum MAC addresses for all VLANs on this + interface. + vlans: + type: list + primary_key: range + items: + type: dict + keys: + range: + type: str + convert_types: + - int + description: "VLAN ID or range(s) of VLAN IDs, <1-4094>.\nExample:\n + \ - 3\n - 1,3\n - 1-10\n" + mac_address_maximum: + type: int + convert_types: + - str + validate_state: + type: bool + description: Set to false to disable interface validation by the `eos_validate_state` + role. eos_cli: type: str description: Multiline EOS CLI rendered directly on the port-channel interface - in the final EOS configuration + in the final EOS configuration. + esi: + type: str + description: 'EVPN Ethernet Segment Identifier (Type 1 format). + + ' + deprecation: + removed: true + warning: true + new_key: evpn_ethernet_segment.identifier + remove_in_version: 5.0.0 + rt: + type: str + description: 'EVPN Route Target for ESI with format xx:xx:xx:xx:xx:xx. + + ' + deprecation: + removed: true + warning: true + new_key: evpn_ethernet_segment.route_target + remove_in_version: 5.0.0 prefix_lists: type: list primary_key: name @@ -6522,7 +10475,7 @@ keys: keys: name: type: str - description: Prefix-list Name + description: Prefix-list Name. sequence_numbers: type: list primary_key: sequence @@ -6531,15 +10484,17 @@ keys: keys: sequence: type: int - description: Sequence ID + description: Sequence ID. convert_types: - str action: type: str required: true - description: 'Action as string + description: 'Action as string. + + Example: "permit 10.255.0.0/27 eq 32" - Example: "permit 10.255.0.0/27 eq 32"' + ' priority_flow_control: type: dict description: 'Global Priority Flow Control settings. @@ -6609,7 +10564,9 @@ keys: ' override_action_drop: type: bool - description: Override configured action on stuck queue to drop. + description: 'Override configured action on stuck queue to drop. + + ' prompt: type: str ptp: @@ -6619,17 +10576,28 @@ keys: type: str valid_values: - boundary - - transparent + - disabled + - e2etransparent + - gptp + - ordinarymaster + - p2ptransparent + profile: + type: str + valid_values: + - g8275.1 + - g8275.2 + mode_one_step: + type: bool forward_unicast: type: bool clock_identity: type: str - description: The clock-id in xx:xx:xx:xx:xx:xx format + description: The clock-id in xx:xx:xx:xx:xx:xx format. source: type: dict keys: ip: - description: Source IP + description: Source IP. type: str priority1: type: int @@ -6780,6 +10748,13 @@ keys: type: str description: 'Example: "8 9 10 to traffic-class 1" + ' + exp: + type: list + items: + type: str + description: 'Example "0 to traffic-class 0" + ' traffic_class: type: list @@ -6792,11 +10767,11 @@ keys: type: bool random_detect: type: dict - description: Global random-detect settings + description: Global random-detect settings. keys: ecn: type: dict - description: Global ECN Configuration + description: Global ECN Configuration. keys: allow_non_ect: type: dict @@ -6809,7 +10784,7 @@ keys: Check which command is required for your platform.' chip_based: type: bool - description: Allow non-ect chip-based + description: Allow non-ect chip-based. qos_profiles: type: list primary_key: name @@ -6818,7 +10793,7 @@ keys: keys: name: type: str - description: Profile-Name + description: Profile-Name. trust: type: str valid_values: @@ -6838,7 +10813,7 @@ keys: keys: rate: type: str - description: 'Supported options are platform dependent + description: 'Supported options are platform dependent. Example: "< rate > kbps", "1-100 percent", "< rate > pps" @@ -6851,7 +10826,7 @@ keys: keys: qos_input: type: str - description: Policy-map name + description: Policy-map name. tx_queues: type: list primary_key: id @@ -6862,7 +10837,7 @@ keys: type: int convert_types: - str - description: TX-Queue ID + description: TX-Queue ID. bandwidth_percent: type: int convert_types: @@ -6881,24 +10856,24 @@ keys: keys: rate: type: str - description: 'Supported options are platform dependent + description: 'Supported options are platform dependent. Example: "< rate > kbps", "1-100 percent", "< rate > pps" ' comment: type: str - description: Text comment added to queue + description: Text comment added to queue. random_detect: type: dict keys: ecn: - description: Explicit Congestion Notification + description: Explicit Congestion Notification. type: dict keys: count: type: bool - description: Enable counter for random-detect ECNs + description: Enable counter for random-detect ECNs. threshold: type: dict keys: @@ -6920,28 +10895,81 @@ keys: min: 1 convert_types: - str - description: Random-detect ECN minimum-threshold + description: Random-detect ECN minimum-threshold. max: type: int required: true min: 1 convert_types: - str - description: Random-detect ECN maximum-threshold + description: Random-detect ECN maximum-threshold. max_probability: type: int min: 1 max: 100 convert_types: - str - description: Random-detect ECN maximum mark probability + description: Random-detect ECN maximum mark probability. + weight: + type: int + min: 0 + max: 15 + convert_types: + - str + description: Random-detect ECN weight. + drop: + description: Set WRED parameters. + type: dict + keys: + threshold: + type: dict + keys: + units: + required: true + type: str + valid_values: + - segments + - bytes + - kbytes + - mbytes + - microseconds + - milliseconds + description: Units to be used for the threshold values. + drop_precedence: + type: int + required: false + min: 0 + max: 2 + description: Specify Drop Precedence value. + min: + type: int + required: true + min: 1 + convert_types: + - str + description: WRED minimum-threshold. + max: + type: int + required: true + min: 1 + convert_types: + - str + description: WRED maximum-threshold. + drop_probability: + type: int + required: true + min: 1 + max: 100 + convert_types: + - str + description: WRED drop probability. weight: type: int min: 0 max: 15 convert_types: - str - description: Random-detect ECN weight + description: WRED weight. uc_tx_queues: type: list primary_key: id @@ -6952,7 +10980,7 @@ keys: type: int convert_types: - str - description: UC TX queue ID + description: UC TX queue ID. bandwidth_percent: type: int convert_types: @@ -6971,24 +10999,24 @@ keys: keys: rate: type: str - description: 'Supported options are platform dependent + description: 'Supported options are platform dependent. Example: "< rate > kbps", "1-100 percent", "< rate > pps" ' comment: type: str - description: Text comment added to queue + description: Text comment added to queue. random_detect: type: dict keys: ecn: - description: Explicit Congestion Notification + description: Explicit Congestion Notification. type: dict keys: count: type: bool - description: Enable counter for random-detect ECNs + description: Enable counter for random-detect ECNs. threshold: type: dict keys: @@ -7001,35 +11029,88 @@ keys: - kbytes - mbytes - milliseconds - description: Unit to be used for the threshold values + description: Unit to be used for the threshold values. min: type: int required: true min: 1 convert_types: - str - description: Random-detect ECN minimum-threshold + description: Random-detect ECN minimum-threshold. max: type: int required: true min: 1 convert_types: - str - description: Random-detect ECN maximum-threshold + description: Random-detect ECN maximum-threshold. max_probability: type: int min: 1 max: 100 convert_types: - str - description: Random-detect ECN maximum mark probability + description: Random-detect ECN maximum mark probability. + weight: + type: int + min: 0 + max: 15 + convert_types: + - str + description: Random-detect ECN weight. + drop: + description: Set WRED parameters. + type: dict + keys: + threshold: + type: dict + keys: + units: + required: true + type: str + valid_values: + - segments + - bytes + - kbytes + - mbytes + - microseconds + - milliseconds + description: Units to be used for the threshold values. + drop_precedence: + type: int + required: false + min: 0 + max: 2 + description: Specify Drop Precedence value. + min: + type: int + required: true + min: 1 + convert_types: + - str + description: WRED minimum-threshold. + max: + type: int + required: true + min: 1 + convert_types: + - str + description: WRED maximum-threshold. + drop_probability: + type: int + required: true + min: 1 + max: 100 + convert_types: + - str + description: WRED drop probability. weight: type: int min: 0 max: 15 convert_types: - str - description: Random-detect ECN weight + description: WRED weight. mc_tx_queues: type: list primary_key: id @@ -7040,7 +11121,7 @@ keys: type: int convert_types: - str - description: MC TX queue ID + description: MC TX queue ID. bandwidth_percent: type: int convert_types: @@ -7059,7 +11140,7 @@ keys: keys: rate: type: str - description: 'Supported options are platform dependent + description: 'Supported options are platform dependent. Example: "< rate > kbps", "1-100 percent", "< rate > pps" @@ -7071,7 +11152,7 @@ keys: ' priority_flow_control: type: dict - description: 'Priority Flow Control settings + description: 'Priority Flow Control settings. ' keys: @@ -7123,7 +11204,7 @@ keys: should start dropping on congested priorities. - This should be decimal with up to 2 decimal point + This should be decimal with up to 2 decimal point. Example: 0.01 or 60 @@ -7174,7 +11255,7 @@ keys: priorities: type: list primary_key: priority - description: 'Set the drop/no_drop on each queue + description: 'Set the drop/no_drop on each queue. ' items: @@ -7187,13 +11268,15 @@ keys: required: true convert_types: - str - description: 'Priority queue number (COS value) + description: 'Priority queue number (COS value). ' no_drop: type: bool required: true - description: Enable Priority Flow Control frames on this queue + description: 'Enable Priority Flow Control frames on this queue. + + ' queue_monitor_length: type: dict keys: @@ -7224,11 +11307,11 @@ keys: type: int convert_types: - str - description: Logging interval in seconds + description: Logging interval in seconds. notifying: type: bool description: Should only be used for platforms supporting the "queue-monitor - length notifying" CLI + length notifying" CLI. cpu: type: dict keys: @@ -7244,6 +11327,9 @@ keys: type: int convert_types: - str + tx_latency: + type: bool + description: Enable tx-latency mode. queue_monitor_streaming: type: dict keys: @@ -7251,10 +11337,10 @@ keys: type: bool ip_access_group: type: str - description: Name of IP ACL + description: Name of IP ACL. ipv6_access_group: type: str - description: Name of IPv6 ACL + description: Name of IPv6 ACL. max_connections: type: int convert_types: @@ -7286,10 +11372,10 @@ keys: max: 65535 convert_types: - str - description: TCP Port + description: TCP Port. tls_ssl_profile: type: str - description: Name of TLS profile + description: Name of TLS profile. hosts: type: list primary_key: host @@ -7298,11 +11384,28 @@ keys: keys: host: type: str - description: Host IP address or name + description: Host IP address or name. vrf: type: str convert_types: - int + tls: + type: dict + description: When TLS is configured, `key` is ignored.. + keys: + enabled: + type: bool + description: Enable TLS for radius-server. + ssl_profile: + type: str + description: Name of TLS profile. + port: + type: int + min: 0 + max: 65535 + convert_types: + - str + description: TCP Port used for TLS. EOS default is 2083. timeout: type: int min: 1 @@ -7317,32 +11420,27 @@ keys: - str key: type: str - description: Encrypted key + description: 'Encrypted key - only type 7 supported. + + When TLS is configured, `key` is ignored.' + tls_ssl_profile: + type: str + description: Name of global TLS profile. radius_servers: + documentation_options: + table: radius-server deprecation: warning: true + removed: true new_key: radius_server.hosts remove_in_version: v5.0.0 type: list - items: - type: dict - keys: - host: - type: str - description: Host IP address or name - vrf: - type: str - convert_types: - - int - key: - type: str - description: Encrypted key redundancy: type: dict keys: protocol: type: str - description: Redundancy Protocol + description: Redundancy Protocol. roles: type: list items: @@ -7350,7 +11448,7 @@ keys: keys: name: type: str - description: Role name + description: Role name. sequence_numbers: type: list items: @@ -7360,7 +11458,7 @@ keys: type: int convert_types: - str - description: Sequence number + description: Sequence number. action: type: str valid_values: @@ -7368,12 +11466,12 @@ keys: - deny mode: type: str - description: '"config", "config-all", "exec" or mode key as string + description: '"config", "config-all", "exec" or mode key as string. ' command: type: str - description: Command as string + description: Command as string. route_maps: type: list primary_key: name @@ -7382,7 +11480,7 @@ keys: keys: name: type: str - description: Route-map Name + description: Route-map Name. sequence_numbers: type: list required: true @@ -7392,7 +11490,7 @@ keys: keys: sequence: type: int - description: Sequence ID + description: Sequence ID. convert_types: - str type: @@ -7405,45 +11503,190 @@ keys: type: str match: type: list - description: List of "match" statements + description: List of "match" statements. items: type: str - description: 'Match as string + description: 'Match as string. Example: "ip address prefix-list PL-LOOPBACKS-EVPN-OVERLAY" ' set: type: list - description: List of "set" statements + description: List of "set" statements. items: type: str - description: 'Set as string + description: 'Set as string. Example: "origin incomplete" ' sub_route_map: type: str - description: Name of Sub-Route-map + description: Name of Sub-Route-map. continue: type: dict keys: - enabled: - type: bool - sequence_number: + enabled: + type: bool + sequence_number: + type: int + convert_types: + - str + router_adaptive_virtual_topology: + type: dict + keys: + topology_role: + description: Role name. + type: str + valid_values: + - edge + - pathfinder + - transit region + - transit zone + gateway_vxlan: + description: 'Enables VXLAN gateway router profile. + + Only applicable for `topology_role: edge`, `topology_role: transit region` + or `topology_role: transit zone`.' + type: bool + region: + type: dict + description: Region name and ID. + keys: + name: + type: str + required: true + pattern: ^[A-Za-z0-9_.:{}\[\]-]+$ + id: + type: int + convert_types: + - str + required: true + min: 1 + max: 255 + zone: + type: dict + description: Zone name and ID. + keys: + name: + type: str + required: true + pattern: ^[A-Za-z0-9_.:{}\[\]-]+$ + id: + type: int + convert_types: + - str + required: true + min: 1 + max: 10000 + site: + type: dict + description: Site name and ID. + keys: + name: + type: str + required: true + pattern: ^[A-Za-z0-9_.:{}\[\]-]+$ + id: + type: int + convert_types: + - str + required: true + min: 1 + max: 10000 + profiles: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: AVT Name. + load_balance_policy: + type: str + description: Name of the load-balance policy. + internet_exit_policy: + type: str + description: Name of the internet exit policy. + policies: + type: list + primary_key: name + description: A sequence of application profiles mapped to some virtual topologies. + items: + type: dict + keys: + name: + type: str + description: Policy name. + matches: + type: list + items: + type: dict + keys: + application_profile: + type: str + description: Application profile name. + avt_profile: + type: str + description: AVT Profile name. + dscp: + type: int + convert_types: + - str + min: 0 + max: 63 + description: Set DSCP for matched traffic. + traffic_class: + type: int + convert_types: + - str + min: 0 + max: 7 + description: Set traffic-class for matched traffic. + vrfs: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: VRF name. + policy: + type: str + description: AVT Policy name. + profiles: + type: list + primary_key: id + description: AVT profiles in this VRF. + items: + type: dict + keys: + name: + type: str + description: AVT profile name. + id: type: int + description: Unique ID for this AVT (per VRF). + required: true convert_types: - str + min: 1 + max: 254 router_bfd: type: dict keys: interval: type: int - description: Rate in milliseconds + description: Rate in milliseconds. + local_address: + type: str + description: Configure BFD local IP/IPv6 address. min_rx: type: int - description: Rate in milliseconds + description: Rate in milliseconds. multiplier: type: int min: 3 @@ -7453,14 +11696,26 @@ keys: keys: interval: type: int - description: Rate in milliseconds + description: Rate in milliseconds. min_rx: type: int - description: Rate in milliseconds + description: Rate in milliseconds. multiplier: type: int min: 3 max: 50 + session_snapshot_interval: + type: int + convert_types: + - str + min: 1 + max: 3600 + description: 'Interval in seconds. + + Intervals below 10 are considered "dangerous" on EOS and must have `session_snapshot_interval_dangerous` + set to `true`.' + session_snapshot_interval_dangerous: + type: bool sbfd: type: dict keys: @@ -7469,7 +11724,7 @@ keys: keys: name: type: str - description: Interface Name + description: Interface Name. protocols: type: dict keys: @@ -7479,31 +11734,46 @@ keys: type: bool initiator_interval: type: int - description: Rate in milliseconds + description: Rate in milliseconds. initiator_multiplier: type: int min: 3 max: 50 + initiator_measurement_round_trip: + type: bool + description: Enable round-trip delay measurement. reflector: type: dict keys: min_rx: type: int - description: Rate in milliseconds + description: Rate in milliseconds. local_discriminator: type: str - description: IPv4 address or 32 bit integer + description: IPv4 address or 32 bit integer. router_bgp: type: dict keys: as: type: str - description: BGP AS <1-4294967295> or AS number in asdot notation <1-65535>.<0-65535> + description: 'BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + + For asdot notation in YAML inputs, the value must be put in quotes, to prevent + it from being interpreted as a float number.' convert_types: - int + as_notation: + display_name: ASN Notation + type: str + description: BGP AS can be deplayed in the asplain <1-4294967295> or asdot + notation "<1-65535>.<0-65535>". This flag indicates which mode is preferred + - asplain is the default. + valid_values: + - asdot + - asplain router_id: type: str - description: In IP address format A.B.C.D + description: In IP address format A.B.C.D. distance: type: dict keys: @@ -7539,14 +11809,14 @@ keys: - str min: 1 max: 3600 - description: Number of seconds + description: Number of seconds. stalepath_time: type: int convert_types: - str min: 1 max: 3600 - description: Number of seconds + description: Number of seconds. graceful_restart_helper: type: dict keys: @@ -7611,10 +11881,10 @@ keys: ' bgp_cluster_id: type: str - description: IP Address A.B.C.D + description: IP Address A.B.C.D. bgp_defaults: type: list - description: BGP command as string + description: BGP command as string. items: type: str bgp: @@ -7643,10 +11913,17 @@ keys: keys: d_path: type: bool + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths + redistribute_internal: + type: bool + description: Allow redistribution of iBGP routes into an Interior Gateway + Protocol (IGP). EOS default is true. listen_ranges: type: list description: 'Improved "listen_ranges" data model to support multiple listen - ranges and additional filter capabilities + ranges and additional filter capabilities. ' items: @@ -7654,16 +11931,16 @@ keys: keys: prefix: type: str - description: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I" + description: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I". peer_id_include_router_id: type: bool - description: Include router ID as part of peer filter + description: Include router ID as part of peer filter. peer_group: type: str - description: Peer group name + description: Peer group name. peer_filter: type: str - description: 'Peer-filter name + description: 'Peer-filter name. note: `peer_filter` or `remote_as` is required but mutually exclusive. @@ -7674,7 +11951,10 @@ keys: type: str convert_types: - int - description: BGP AS <1-4294967295> or AS number in asdot notation <1-65535>.<0-65535> + description: 'BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number.' peer_groups: type: list primary_key: name @@ -7683,18 +11963,24 @@ keys: keys: name: type: str - description: Peer-group name + description: Peer-group name. type: type: str - description: Key only used for documentation or validation purposes + description: Key only used for documentation or validation purposes. remote_as: type: str - description: BGP AS <1-4294967295> or AS number in asdot notation <1-65535>.<0-65535> + description: 'BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number.' convert_types: - int local_as: type: str - description: BGP AS <1-4294967295> or AS number in asdot notation <1-65535>.<0-65535> + description: 'BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number.' convert_types: - int description: @@ -7703,17 +11989,17 @@ keys: type: bool as_path: type: dict - description: BGP AS-PATH options + description: BGP AS-PATH options. keys: remote_as_replace_out: type: bool - description: Replace AS number with local AS number + description: Replace AS number with local AS number. prepend_own_disabled: type: bool - description: Disable prepending own AS number to AS path + description: Disable prepending own AS number to AS path. remove_private_as: type: dict - description: Remove private AS numbers in outbound AS path + description: Remove private AS numbers in outbound AS path. keys: enabled: type: bool @@ -7728,34 +12014,49 @@ keys: type: bool replace_as: type: bool - peer_filter: - type: str - description: 'Peer-filter name - - note: `bgp_listen_range_prefix` and `peer_filter` should not be mixed - with - - the new `listen_ranges` key above to avoid conflicts. - - ' - deprecation: - warning: true - remove_in_version: 5.0.0 - new_key: listen_ranges next_hop_unchanged: type: bool update_source: type: str - description: IP address or interface name + description: IP address or interface name. route_reflector_client: type: bool bfd: type: bool + description: Enable BFD. + bfd_timers: + type: dict + description: 'Override default BFD timers. BFD must be enabled with + `bfd: true`.' + keys: + interval: + type: int + convert_types: + - str + min: 50 + max: 60000 + required: true + description: Interval in milliseconds. + min_rx: + type: int + convert_types: + - str + min: 50 + max: 60000 + required: true + description: Rate in milliseconds. + multiplier: + type: int + min: 3 + max: 50 + required: true + convert_types: + - str ebgp_multihop: type: int min: 1 max: 255 - description: Time-to-live in range of hops + description: Time-to-live in range of hops. convert_types: - str next_hop_self: @@ -7773,14 +12074,14 @@ keys: type: bool route_map: type: str - description: Route-map name + description: Route-map name. send_community: type: str description: '''all'' or a combination of ''standard'', ''extended'', - ''large'' and ''link-bandwidth (w/options)''' + ''large'' and ''link-bandwidth (w/options)''.' maximum_routes: type: int - description: Maximum number of routes (0 means unlimited) + description: Maximum number of routes (0 means unlimited). min: 0 max: 4294967294 convert_types: @@ -7791,13 +12092,65 @@ keys: (0 means never warn) or Percentage of maximum number of routes at which to warn ("<1-100> - percent") + percent"). ' convert_types: - int maximum_routes_warning_only: type: bool + missing_policy: + type: dict + description: Missing policy configuration for all address-families. + keys: + direction_in: + description: Missing policy inbound direction. + type: dict + keys: + action: + description: Missing policy action. + type: str + required: true + valid_values: + - deny + - permit + - deny-in-out + include_community_list: + type: bool + description: Include community-list references in missing policy + decision. + include_prefix_list: + type: bool + description: Include prefix-list references in missing policy + decision. + include_sub_route_map: + type: bool + description: Include sub-route-map references in missing policy + decision. + direction_out: + description: Missing policy outbound direction. + type: dict + keys: + action: + description: Missing policy action. + type: str + required: true + valid_values: + - deny + - permit + - deny-in-out + include_community_list: + type: bool + description: Include community-list references in missing policy + decision. + include_prefix_list: + type: bool + description: Include prefix-list references in missing policy + decision. + include_sub_route_map: + type: bool + description: Include sub-route-map references in missing policy + decision. link_bandwidth: type: dict keys: @@ -7805,7 +12158,7 @@ keys: type: bool default: type: str - description: nn.nn(K|M|G) link speed in bits/second + description: nn.nn(K|M|G) link speed in bits/second. allowas_in: type: dict keys: @@ -7813,7 +12166,7 @@ keys: type: bool times: type: int - description: Number of local ASNs allowed in a BGP update + description: Number of local ASNs allowed in a BGP update. convert_types: - str min: 1 @@ -7827,7 +12180,7 @@ keys: timers: type: str description: BGP Keepalive and Hold Timer values in seconds as string - "<0-3600> <0-3600>" + "<0-3600> <0-3600>". rib_in_pre_policy_retain: type: dict keys: @@ -7837,26 +12190,49 @@ keys: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name - bgp_listen_range_prefix: + description: Outbound route-map name. + session_tracker: + type: str + shared_secret: + type: dict + keys: + profile: + type: str + required: true + description: Name of profile defined under `management_security`. + hash_algorithm: + type: str + required: true + description: 'Note: Algorithm hmac-sha-256 requires EOS version + 4.31.1F and above.' + valid_values: + - aes-128-cmac-96 + - hmac-sha-256 + - hmac-sha1-96 + ttl_maximum_hops: + type: int + convert_types: + - str + min: 0 + max: 254 + description: Maximum number of hops. + peer_filter: type: str - description: 'IP prefix range - - note: `bgp_listen_range_prefix` and `peer_filter` should not be mixed - with - - the new `listen_ranges` key above to avoid conflicts. - - ' deprecation: warning: true + removed: true remove_in_version: 5.0.0 - new_key: listen_ranges - session_tracker: + new_key: router_bgp.listen_ranges[].peer_filter + bgp_listen_range_prefix: type: str + deprecation: + warning: true + removed: true + remove_in_version: 5.0.0 + new_key: router_bgp.listen_ranges[].bgp_listen_range_prefix neighbors: type: list primary_key: ip_address @@ -7869,37 +12245,77 @@ keys: type: str remote_as: type: str - description: BGP AS <1-4294967295> or AS number in asdot notation <1-65535>.<0-65535> + description: 'BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number.' convert_types: - int local_as: type: str - description: BGP AS <1-4294967295> or AS number in asdot notation <1-65535>.<0-65535> + description: 'BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number.' convert_types: - int as_path: type: dict - description: BGP AS-PATH options + description: BGP AS-PATH options. keys: remote_as_replace_out: type: bool - description: Replace AS number with local AS number + description: Replace AS number with local AS number. prepend_own_disabled: type: bool - description: Disable prepending own AS number to AS path + description: Disable prepending own AS number to AS path. + peer: + type: str + description: Key only used for documentation or validation purposes. description: type: str route_reflector_client: type: bool + password: + type: str passive: type: bool shutdown: type: bool update_source: type: str - description: Source Interface + description: Source Interface. bfd: type: bool + description: Enable BFD. + bfd_timers: + type: dict + description: 'Override default BFD timers. BFD must be enabled with + `bfd: true`.' + keys: + interval: + type: int + convert_types: + - str + min: 50 + max: 60000 + required: true + description: Interval in milliseconds. + min_rx: + type: int + convert_types: + - str + min: 50 + max: 60000 + required: true + description: Rate in milliseconds. + multiplier: + type: int + min: 3 + max: 50 + required: true + convert_types: + - str weight: type: int min: 0 @@ -7909,13 +12325,13 @@ keys: timers: type: str description: BGP Keepalive and Hold Timer values in seconds as string - "<0-3600> <0-3600>" + "<0-3600> <0-3600>". route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. default_originate: type: dict keys: @@ -7928,10 +12344,10 @@ keys: send_community: type: str description: '''all'' or a combination of ''standard'', ''extended'', - ''large'' and ''link-bandwidth (w/options)''' + ''large'' and ''link-bandwidth (w/options)''.' maximum_routes: type: int - description: Maximum number of routes (0 means unlimited) + description: Maximum number of routes (0 means unlimited). min: 0 max: 4294967294 convert_types: @@ -7942,13 +12358,65 @@ keys: (0 means never warn) or Percentage of maximum number of routes at which to warn ("<1-100> - percent") + percent"). ' convert_types: - int maximum_routes_warning_only: type: bool + missing_policy: + type: dict + description: Missing policy configuration for all address-families. + keys: + direction_in: + description: Missing policy inbound direction. + type: dict + keys: + action: + description: Missing policy action. + type: str + required: true + valid_values: + - deny + - permit + - deny-in-out + include_community_list: + type: bool + description: Include community-list references in missing policy + decision. + include_prefix_list: + type: bool + description: Include prefix-list references in missing policy + decision. + include_sub_route_map: + type: bool + description: Include sub-route-map references in missing policy + decision. + direction_out: + description: Missing policy outbound direction. + type: dict + keys: + action: + description: Missing policy action. + type: str + required: true + valid_values: + - deny + - permit + - deny-in-out + include_community_list: + type: bool + description: Include community-list references in missing policy + decision. + include_prefix_list: + type: bool + description: Include prefix-list references in missing policy + decision. + include_sub_route_map: + type: bool + description: Include sub-route-map references in missing policy + decision. allowas_in: type: dict keys: @@ -7960,12 +12428,12 @@ keys: - str min: 1 max: 10 - description: Number of local ASNs allowed in a BGP update + description: Number of local ASNs allowed in a BGP update. ebgp_multihop: type: int min: 1 max: 255 - description: Time-to-live in range of hops + description: Time-to-live in range of hops. convert_types: - str next_hop_self: @@ -7977,7 +12445,7 @@ keys: type: bool default: type: str - description: nn.nn(K|M|G) link speed in bits/second + description: nn.nn(K|M|G) link speed in bits/second. rib_in_pre_policy_retain: type: dict keys: @@ -7987,7 +12455,7 @@ keys: type: bool remove_private_as: type: dict - description: Remove private AS numbers in outbound AS path + description: Remove private AS numbers in outbound AS path. keys: enabled: type: bool @@ -8004,6 +12472,29 @@ keys: type: bool session_tracker: type: str + shared_secret: + type: dict + keys: + profile: + type: str + required: true + description: Name of profile defined under `management_security`. + hash_algorithm: + type: str + required: true + description: 'Note: Algorithm hmac-sha-256 requires EOS version + 4.31.1F and above.' + valid_values: + - aes-128-cmac-96 + - hmac-sha-256 + - hmac-sha1-96 + ttl_maximum_hops: + type: int + convert_types: + - str + min: 0 + max: 254 + description: Maximum number of hops. neighbor_interfaces: type: list primary_key: name @@ -8012,11 +12503,18 @@ keys: keys: name: type: str - description: Interface name + description: Interface name. remote_as: type: str convert_types: - int + description: 'BGP AS <1-4294967295> or AS number in asdot notation "<1-65535>.<0-65535>". + + For asdot notation in YAML inputs, the value must be put in quotes, + to prevent it from being interpreted as a float number.' + peer: + type: str + description: Key only used for documentation or validation purposes. peer_group: type: str default: Peer-group name @@ -8024,7 +12522,7 @@ keys: type: str peer_filter: type: str - description: Peer-filter name + description: Peer-filter name. aggregate_addresses: type: list primary_key: prefix @@ -8033,7 +12531,7 @@ keys: keys: prefix: type: str - description: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I" + description: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I". advertise_only: type: bool as_set: @@ -8042,22 +12540,57 @@ keys: type: bool attribute_map: type: str - description: Route-map name + description: Route-map name. match_map: type: str - description: Route-map name + description: Route-map name. redistribute_routes: type: list primary_key: source_protocol + allow_duplicate_primary_key: true items: type: dict keys: source_protocol: type: str + valid_values: + - attached-host + - bgp + - connected + - dynamic + - isis + - ospf + - ospfv3 + - rip + - static + - user route_map: type: str + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` takes precedence. + + Only applicable if `source_protocol` is one of `connected`, `static`, + `isis`, `user`, `dynamic`.' include_leaked: type: bool + ospf_route_type: + type: str + valid_values: + - external + - internal + - nssa-external + - nssa-external 1 + - nssa-external 2 + description: 'Routes learned by the OSPF protocol. + + The `ospf_route_type` is valid for source_protocols ''ospf'' and ''ospfv3''. + + ' vlan_aware_bundles: type: list primary_key: name @@ -8066,15 +12599,15 @@ keys: keys: name: type: str - description: VLAN aware bundle name + description: VLAN aware bundle name. tenant: type: str - description: Key only used for documentation or validation purposes + description: Key only used for documentation or validation purposes. description: type: str - description: Key only used for documentation or validation purposes + description: Key only used for documentation or validation purposes. rd: - description: Route distinguisher + description: Route distinguisher. type: str rd_evpn_domain: type: dict @@ -8086,7 +12619,7 @@ keys: - all rd: type: str - description: Route distinguisher + description: Route distinguisher. route_targets: type: dict keys: @@ -8148,13 +12681,13 @@ keys: type: str vlan: type: str - description: VLAN range as string. Example "100-200,300" + description: VLAN range as string. Example "100-200,300". convert_types: - int eos_cli: type: str description: Multiline EOS CLI rendered directly on the Router BGP, - VLAN-aware-bundle definition in the final EOS configuration + VLAN-aware-bundle definition in the final EOS configuration. vlans: type: list primary_key: id @@ -8167,9 +12700,9 @@ keys: - str tenant: type: str - description: Key only used for documentation or validation purposes + description: Key only used for documentation or validation purposes. rd: - description: Route distinguisher + description: Route distinguisher. type: str rd_evpn_domain: type: dict @@ -8181,11 +12714,11 @@ keys: - all rd: type: str - description: Route distinguisher + description: Route distinguisher. eos_cli: type: str description: Multiline EOS CLI rendered directly on the Router BGP, - VLAN definition in the final EOS configuration + VLAN definition in the final EOS configuration. route_targets: type: dict keys: @@ -8253,16 +12786,16 @@ keys: keys: name: type: str - description: VPWS instance name + description: VPWS instance name. rd: - description: Route distinguisher + description: Route distinguisher. type: str route_targets: type: dict keys: import_export: type: str - description: Route Target + description: Route Target. mpls_control_word: type: bool label_flow: @@ -8279,17 +12812,17 @@ keys: keys: name: type: str - description: Pseudowire name + description: Pseudowire name. id_local: type: int convert_types: - str - description: Must match id_remote on other pe + description: Must match id_remote on other pe. id_remote: type: int convert_types: - str - description: Must match id_local on other pe + description: Must match id_local on other pe. address_family_evpn: type: dict keys: @@ -8303,8 +12836,10 @@ keys: valid_values: - vxlan - mpls + - path-selection + description: Transport encapsulation for neighbor. next_hop_self_source_interface: - description: Source interface name + description: Source interface name. type: str next_hop_self_received_evpn_routes: type: dict @@ -8313,6 +12848,70 @@ keys: type: bool inter_domain: type: bool + next_hop_mpls_resolution_ribs: + type: list + min_length: 1 + max_length: 3 + description: Specify the RIBs used to resolve MPLS next-hops. The order + of this list determines the order of RIB lookups. + items: + type: dict + keys: + rib_type: + type: str + required: true + valid_values: + - system-connected + - tunnel-rib-colored + - tunnel-rib + description: Type of RIB. For 'tunnel-rib', use 'rib_name' to specify + the name of the Tunnel-RIB to use. + rib_name: + type: str + description: The name of the tunnel-rib to use when using 'tunnel-rib' + type. + neighbors: + type: list + primary_key: ip_address + items: + type: dict + keys: + ip_address: + type: str + activate: + type: bool + rcf_in: + type: str + description: 'Inbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + rcf_out: + type: str + description: 'Outbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + default_route: + type: dict + keys: + enabled: + type: bool + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg).' + route_map: + type: str + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths + encapsulation: + type: str + valid_values: + - vxlan + - mpls + - path-selection + description: Transport encapsulation for the neighbor. peer_groups: type: list primary_key: name @@ -8321,15 +12920,37 @@ keys: keys: name: type: str - description: Peer-group name + description: Peer-group name. activate: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. + rcf_in: + type: str + description: 'Inbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + rcf_out: + type: str + description: 'Outbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + default_route: + type: dict + keys: + enabled: + type: bool + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg).' + route_map: + type: str domain_remote: type: bool encapsulation: @@ -8337,6 +12958,11 @@ keys: valid_values: - vxlan - mpls + - path-selection + description: Transport encapsulation for the peer-group. + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths evpn_hostflap_detection: type: dict keys: @@ -8344,7 +12970,7 @@ keys: type: bool window: type: int - description: Time (in seconds) to detect a MAC duplication issue + description: Time (in seconds) to detect a MAC duplication issue. min: 0 max: 4294967295 convert_types: @@ -8356,14 +12982,14 @@ keys: convert_types: - str description: Minimum number of MAC moves that indicate a MAC Duplication - issue + issue. expiry_timeout: type: int min: 0 max: 4294967295 convert_types: - str - description: Time (in seconds) to purge a MAC duplication issue + description: Time (in seconds) to purge a MAC duplication issue. next_hop: type: dict keys: @@ -8376,6 +13002,72 @@ keys: type: str valid_values: - discard + import_ethernet_segment_ip_mass_withdraw: + type: bool + import_overlay_index_gateway: + type: bool + export_ethernet_segment_ip_mass_withdraw: + type: bool + next_hop_unchanged: + type: bool + bgp_additional_paths: + type: dict + deprecation: + warning: true + remove_in_version: 6.0.0 + new_key: bgp.additional_paths + description: BGP additional-paths commands. + keys: + receive: + type: bool + description: Receive multiple paths. + send: + type: dict + description: Send multiple paths. + keys: + any: + type: bool + description: Any eligible path. + backup: + type: bool + description: Best path and installed backup path. + ecmp: + type: bool + description: All paths in best path ECMP group. + ecmp_limit: + type: int + description: Amount of ECMP paths to send. + convert_types: + - str + min: 2 + max: 64 + limit: + type: int + description: Amount of paths to send. + convert_types: + - str + min: 2 + max: 64 + bgp: + type: dict + keys: + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths + layer_2_fec_in_place_update: + type: dict + description: BGP layer-2 in-place FEC operation. + keys: + enabled: + type: bool + required: true + timeout: + type: int + description: In-place FEC update tracking timeout in seconds. + convert_types: + - str + min: 0 + max: 300 address_family_rtc: type: dict keys: @@ -8387,7 +13079,7 @@ keys: keys: name: type: str - description: Peer-group name + description: Peer-group name. activate: type: bool default_route_target: @@ -8407,92 +13099,613 @@ keys: type: dict keys: prefix: - description: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I" + description: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I". + type: str + route_map: + description: Route-map name. + type: str + bgp: + type: dict + keys: + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths + keys: + install: + type: bool + description: Install BGP backup path. + install_ecmp_primary: + type: bool + description: Allow additional path with ECMP primary path. + redistribute_internal: + type: bool + description: Allow redistribution of iBGP routes into an Interior + Gateway Protocol (IGP). EOS default is true. + peer_groups: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: Peer-group name. + activate: + type: bool + route_map_in: + type: str + description: Inbound route-map name. + route_map_out: + type: str + description: Outbound route-map name. + rcf_in: + type: str + description: 'Inbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + rcf_out: + type: str + description: 'Outbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + default_originate: + type: dict + keys: + always: + type: bool + route_map: + description: Route-map name. + type: str + prefix_list_in: + type: str + description: Inbound prefix-list name. + prefix_list_out: + type: str + description: Outbound prefix-list name. + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths + keys: + prefix_list: + type: str + description: Apply the configurations only to the routes matching + the prefix list. + next_hop: + type: dict + keys: + address_family_ipv6: + type: dict + keys: + enabled: + type: bool + required: true + originate: + type: bool + address_family_ipv6_originate: + type: bool + deprecation: + warning: true + removed: true + new_key: address_family_ipv6 + remove_in_version: 5.0.0 + neighbors: + type: list + primary_key: ip_address + items: + type: dict + keys: + ip_address: + type: str + activate: + type: bool + route_map_in: + type: str + description: Inbound route-map name. + route_map_out: + type: str + description: Outbound route-map name. + rcf_in: + type: str + description: 'Inbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + rcf_out: + type: str + description: 'Outbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + prefix_list_in: + type: str + description: Inbound prefix-list name. + prefix_list_out: + type: str + description: Prefix-list name. + default_originate: + type: dict + keys: + always: + type: bool + route_map: + type: str + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths + keys: + prefix_list: + type: str + description: Apply the configurations only to the routes matching + the prefix list. + redistribute_routes: + type: list + primary_key: source_protocol + allow_duplicate_primary_key: true + items: + type: dict + keys: + source_protocol: + type: str + valid_values: + - attached-host + - bgp + - connected + - dynamic + - isis + - ospf + - ospfv3 + - rip + - static + - user + route_map: + type: str + include_leaked: + type: bool + description: Only applicable if `source_protocol` is one of `connected`, + `static`, `isis`, `ospf`, `ospfv3`. + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` takes + precedence. + + Only applicable if `source_protocol` is one of `connected`, `static`, + `isis`, `user`, `dynamic`.' + ospf_route_type: + type: str + valid_values: + - external + - internal + - nssa-external + - nssa-external 1 + - nssa-external 2 + description: 'Routes learned by the OSPF protocol. + + The `ospf_route_type` is valid for source_protocols ''ospf'' and + ''ospfv3''. + + ' + address_family_ipv4_labeled_unicast: + type: dict + keys: + aigp_session: + type: dict + keys: + confederation: + type: bool + ebgp: + type: bool + ibgp: + type: bool + bgp: + type: dict + keys: + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths + missing_policy: + type: dict + description: Missing policy configuration for all address-families. + keys: + direction_in: + description: Missing policy inbound direction. + type: dict + keys: + action: + description: Missing policy action. + type: str + required: true + valid_values: + - deny + - permit + - deny-in-out + include_community_list: + type: bool + description: Include community-list references in missing + policy decision. + include_prefix_list: + type: bool + description: Include prefix-list references in missing policy + decision. + include_sub_route_map: + type: bool + description: Include sub-route-map references in missing policy + decision. + direction_out: + description: Missing policy outbound direction. + type: dict + keys: + action: + description: Missing policy action. + type: str + required: true + valid_values: + - deny + - permit + - deny-in-out + include_community_list: + type: bool + description: Include community-list references in missing + policy decision. + include_prefix_list: + type: bool + description: Include prefix-list references in missing policy + decision. + include_sub_route_map: + type: bool + description: Include sub-route-map references in missing policy + decision. + next_hop_unchanged: + type: bool + graceful_restart: + type: bool + label_local_termination: + type: str + valid_values: + - explicit-null + - implicit-null + lfib_entry_installation_skipped: + type: bool + description: Skip LFIB entry installation and next hop self route advertisements. + neighbor_default: + type: dict + keys: + next_hop_self: + type: bool + peer_groups: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: Peer-group name. + activate: + type: bool + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths + aigp_session: + type: bool + graceful_restart: + type: bool + graceful_restart_helper: + type: dict + keys: + stale_route_map: + type: str + maximum_advertised_routes: + type: int + description: Maximum number of routes (0 means unlimited). + min: 0 + max: 4294967294 + convert_types: + - str + maximum_advertised_routes_warning_limit: + type: str + convert_types: + - int + description: 'Maximum number of routes after which a warning is + issued (0 means never warn) or + + Percentage of maximum number of routes at which to warn ("<1-100> + percent"). + + ' + missing_policy: + type: dict + description: Missing policy configuration for BGP Labeled-Unicast + neighbor. + keys: + direction_in: + description: Missing policy inbound direction. + type: dict + keys: + action: + description: Missing policy action. + type: str + required: true + valid_values: + - deny + - permit + - deny-in-out + include_community_list: + type: bool + description: Include community-list references in missing + policy decision. + include_prefix_list: + type: bool + description: Include prefix-list references in missing policy + decision. + include_sub_route_map: + type: bool + description: Include sub-route-map references in missing + policy decision. + direction_out: + description: Missing policy outbound direction. + type: dict + keys: + action: + description: Missing policy action. + type: str + required: true + valid_values: + - deny + - permit + - deny-in-out + include_community_list: + type: bool + description: Include community-list references in missing + policy decision. + include_prefix_list: + type: bool + description: Include prefix-list references in missing policy + decision. + include_sub_route_map: + type: bool + description: Include sub-route-map references in missing + policy decision. + multi_path: + type: bool + next_hop_resolution: + type: dict + keys: + v4_mapped_v6_translation: + type: bool + next_hop_self: + type: bool + next_hop_self_source_interface: + description: Source interface name. type: str - route_map: - description: Route-map name + next_hop_self_v4_mapped_v6_source_interface: + description: v4-mapped-v6 source interface name. Takes precedence + over the next_hop_self_source_interface. type: str - peer_groups: + next_hop_unchanged: + type: bool + rcf_in: + type: str + description: 'Inbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + rcf_out: + type: str + description: 'Outbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + route_map_in: + type: str + description: Inbound route-map name. + route_map_out: + type: str + description: Outbound route-map name. + neighbors: type: list - primary_key: name + primary_key: ip_address items: type: dict keys: - name: + ip_address: type: str - description: Peer-group name activate: type: bool - route_map_in: - type: str - description: Inbound route-map name - route_map_out: - type: str - description: Outbound route-map name - default_originate: + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths + aigp_session: + type: bool + graceful_restart: + type: bool + graceful_restart_helper: type: dict keys: - always: - type: bool - route_map: - description: Route-map name + stale_route_map: type: str - next_hop: + maximum_advertised_routes: + type: int + description: Maximum number of routes (0 means unlimited). + min: 0 + max: 4294967294 + convert_types: + - str + maximum_advertised_routes_warning_limit: + type: str + convert_types: + - int + description: 'Maximum number of routes after which a warning is + issued (0 means never warn) or + + Percentage of maximum number of routes at which to warn ("<1-100> + percent"). + + ' + missing_policy: type: dict + description: Missing policy configuration for BGP Labeled-Unicast + neighbor. keys: - address_family_ipv6: + direction_in: + description: Missing policy inbound direction. type: dict keys: - enabled: + action: + description: Missing policy action. + type: str + required: true + valid_values: + - deny + - permit + - deny-in-out + include_community_list: type: bool + description: Include community-list references in missing + policy decision. + include_prefix_list: + type: bool + description: Include prefix-list references in missing policy + decision. + include_sub_route_map: + type: bool + description: Include sub-route-map references in missing + policy decision. + direction_out: + description: Missing policy outbound direction. + type: dict + keys: + action: + description: Missing policy action. + type: str required: true - originate: + valid_values: + - deny + - permit + - deny-in-out + include_community_list: type: bool - address_family_ipv6_originate: + description: Include community-list references in missing + policy decision. + include_prefix_list: + type: bool + description: Include prefix-list references in missing policy + decision. + include_sub_route_map: + type: bool + description: Include sub-route-map references in missing + policy decision. + multi_path: + type: bool + next_hop_resolution: + type: dict + keys: + v4_mapped_v6_translation: type: bool - deprecation: - warning: true - removed: false - new_key: address_family_ipv6 - remove_in_version: 5.0.0 - prefix_list_in: + next_hop_self: + type: bool + next_hop_self_source_interface: + description: Source interface name. type: str - description: Inbound prefix-list name - prefix_list_out: + next_hop_self_v4_mapped_v6_source_interface: + description: v4-mapped-v6 source interface name. Takes precedence + over the next_hop_self_source_interface. type: str - description: Outbound prefix-list name - neighbors: + next_hop_unchanged: + type: bool + rcf_in: + type: str + description: 'Inbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + rcf_out: + type: str + description: 'Outbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + route_map_in: + type: str + description: Inbound route-map name. + route_map_out: + type: str + description: Outbound route-map name. + networks: + type: list + primary_key: prefix + min_length: 1 + items: + type: dict + keys: + prefix: + description: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I". + type: str + route_map: + description: Route-map name. + type: str + next_hops: type: list primary_key: ip_address + min_length: 1 items: type: dict keys: ip_address: type: str - activate: + lfib_backup_ip_forwarding: type: bool - route_map_in: + next_hop_resolution_ribs: + type: list + min_length: 1 + max_length: 3 + description: Specify the RIBs used to resolve next-hops. The order of + this list determines the order of RIB lookups. + items: + type: dict + keys: + rib_type: type: str - description: Inbound route-map name - route_map_out: + required: true + valid_values: + - system-connected + - tunnel-rib-colored + - tunnel-rib + description: Type of RIB. For 'tunnel-rib', use 'rib_name' to specify + the name of the Tunnel-RIB to use. + rib_name: type: str - description: Outbound route-map name - prefix_list_in: + description: The name of the tunnel-rib to use when using 'tunnel-rib' + type. + tunnel_source_protocols: + type: list + min_length: 1 + max_length: 2 + primary_key: protocol + items: + type: dict + keys: + protocol: type: str - description: Inbound prefix-list name - prefix_list_out: + valid_values: + - isis segment-routing + - ldp + rcf: type: str - description: Prefix-list name - default_originate: - type: dict - keys: - always: - type: bool - route_map: - type: str + description: 'Optional RCF function name with parenthesis. + + Example: MyFunction(myarg).' + update_wait_for_convergence: + type: bool + description: Wait for BGP to converge before sending out any route updates. address_family_ipv4_multicast: type: dict keys: + bgp: + type: dict + keys: + additional_paths: + type: dict + keys: + receive: + type: bool peer_groups: type: list primary_key: name @@ -8501,15 +13714,20 @@ keys: keys: name: type: str - description: Peer-group name + description: Peer-group name. activate: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. + additional_paths: + type: dict + keys: + receive: + type: bool neighbors: type: list primary_key: ip_address @@ -8522,13 +13740,167 @@ keys: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. + additional_paths: + type: dict + keys: + receive: + type: bool + redistribute: + type: dict + description: Redistribute routes in to BGP. + keys: + attached_host: + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + connected: + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + isis: + type: dict + keys: + enabled: + type: bool + required: true + isis_level: + type: str + description: Redistribute IS-IS route level. + valid_values: + - level-1 + - level-2 + - level-1-2 + route_map: + type: str + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` takes + precedence.' + include_leaked: + description: Include following routes while redistributing. + type: bool + ospf: + type: dict + keys: + enabled: + type: bool + description: Redistribute OSPF routes. + match_external: + description: Redistribute OSPF routes learned from external sources. + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + match_internal: + description: Redistribute OSPF routes learned from internal sources. + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + match_nssa_external: + description: Redistribute OSPF routes learned from external NSSA + sources. + type: dict + keys: + enabled: + type: bool + required: true + nssa_type: + description: NSSA External Type Number. + type: int + convert_types: + - str + valid_values: + - 1 + - 2 + route_map: + type: str + route_map: + type: str + ospfv3: + type: dict + keys: + enabled: + type: bool + description: Redistribute OSPFv3 routes. + match_external: + description: Redistribute OSPFv3 routes learned from external + sources. + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + match_internal: + description: Redistribute OSPFv3 routes learned from internal + sources. + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + match_nssa_external: + description: Redistribute OSPFv3 routes learned from external + NSSA sources. + type: dict + keys: + enabled: + type: bool + required: true + nssa_type: + description: NSSA External Type Number. + type: int + convert_types: + - str + valid_values: + - 1 + - 2 + route_map: + type: str + route_map: + type: str + static: + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str redistribute_routes: type: list primary_key: source_protocol + allow_duplicate_primary_key: true + deprecation: + warning: true + remove_in_version: 6.0.0 + new_key: redistribute items: type: dict keys: @@ -8536,6 +13908,33 @@ keys: type: str route_map: type: str + include_leaked: + type: bool + description: Only applicable if `source_protocol` is `isis`. + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` takes + precedence. + + Only applicable if `source_protocol` is `isis`.' + ospf_route_type: + type: str + valid_values: + - external + - internal + - nssa-external + - nssa-external 1 + - nssa-external 2 + description: 'Routes learned by the OSPF protocol. + + The `ospf_route_type` is valid for source_protocols ''ospf'' and + ''ospfv3''. + + ' address_family_ipv4_sr_te: type: dict keys: @@ -8551,10 +13950,10 @@ keys: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. peer_groups: type: list primary_key: name @@ -8563,15 +13962,15 @@ keys: keys: name: type: str - description: Peer-group name + description: Peer-group name. activate: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. address_family_ipv6: type: dict keys: @@ -8582,11 +13981,28 @@ keys: type: dict keys: prefix: - description: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I" + description: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I". type: str route_map: - description: Route-map name + description: Route-map name. type: str + bgp: + type: dict + keys: + redistribute_internal: + type: bool + description: Allow redistribution of iBGP routes into an Interior + Gateway Protocol (IGP). EOS default is true. + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths + keys: + install: + type: bool + description: Install BGP backup path. + install_ecmp_primary: + type: bool + description: Allow additional path with ECMP primary path. peer_groups: type: list primary_key: name @@ -8595,21 +14011,39 @@ keys: keys: name: type: str - description: Peer-group name + description: Peer-group name. activate: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. + rcf_in: + type: str + description: 'Inbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + rcf_out: + type: str + description: 'Outbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' prefix_list_in: type: str - description: Inbound prefix-list name + description: Inbound prefix-list name. prefix_list_out: type: str - description: Outbound prefix-list name + description: Outbound prefix-list name. + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths + keys: + prefix_list: + type: str + description: Apply the configurations only to the routes matching + the prefix list. neighbors: type: list primary_key: ip_address @@ -8622,19 +14056,222 @@ keys: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. + rcf_in: + type: str + description: 'Inbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + rcf_out: + type: str + description: 'Outbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' prefix_list_in: type: str - description: Inbound prefix-list name + description: Inbound prefix-list name. prefix_list_out: type: str - description: Outbound prefix-list name + description: Outbound prefix-list name. + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths + keys: + prefix_list: + type: str + description: Apply the configurations only to the routes matching + the prefix list. + redistribute: + type: dict + description: Redistribute routes in to BGP. + keys: + attached_host: + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + bgp: + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + connected: + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` takes + precedence.' + include_leaked: + description: Include following routes while redistributing. + type: bool + dhcp: + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + dynamic: + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` takes + precedence.' + isis: + type: dict + keys: + enabled: + type: bool + required: true + isis_level: + type: str + description: Redistribute IS-IS route level. + valid_values: + - level-1 + - level-2 + - level-1-2 + route_map: + type: str + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` takes + precedence.' + include_leaked: + description: Include following routes while redistributing. + type: bool + ospfv3: + type: dict + keys: + enabled: + type: bool + description: Redistribute OSPFv3 routes. + match_external: + description: Redistribute OSPFv3 routes learned from external + sources. + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + include_leaked: + description: Include following routes while redistributing. + type: bool + match_internal: + description: Redistribute OSPFv3 routes learned from internal + sources. + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + include_leaked: + description: Include following routes while redistributing. + type: bool + match_nssa_external: + description: Redistribute OSPFv3 routes learned from external + NSSA sources. + type: dict + keys: + enabled: + type: bool + required: true + nssa_type: + description: NSSA External Type Number. + type: int + convert_types: + - str + valid_values: + - 1 + - 2 + route_map: + type: str + include_leaked: + description: Include following routes while redistributing. + type: bool + route_map: + type: str + include_leaked: + description: Include following routes while redistributing. + type: bool + static: + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` takes + precedence.' + include_leaked: + type: bool + description: Include following routes while redistributing. + user: + type: dict + keys: + enabled: + type: bool + required: true + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` takes + precedence.' redistribute_routes: type: list primary_key: source_protocol + allow_duplicate_primary_key: true + deprecation: + warning: true + remove_in_version: 6.0.0 + new_key: redistribute items: type: dict keys: @@ -8644,6 +14281,30 @@ keys: type: str include_leaked: type: bool + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` takes + precedence. + + Only used if `source_protocol` is one of `connected`, `static`, + `isis`, `user`, `dynamic`.' + ospf_route_type: + type: str + valid_values: + - external + - internal + - nssa-external + - nssa-external 1 + - nssa-external 2 + description: 'Routes learned by the OSPF protocol. + + The `ospf_route_type` is valid for source_protocols ''ospfv3''. + + ' address_family_ipv6_multicast: type: dict keys: @@ -8682,10 +14343,15 @@ keys: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. + additional_paths: + type: dict + keys: + receive: + type: bool peer_groups: type: list primary_key: name @@ -8694,9 +14360,14 @@ keys: keys: name: type: str - description: Peer-group name + description: Peer-group name. activate: type: bool + additional_paths: + type: dict + keys: + receive: + type: bool networks: type: list primary_key: prefix @@ -8705,9 +14376,53 @@ keys: keys: prefix: type: str - description: IPv6 prefix "A:B:C:D:E:F:G:H/I" + description: IPv6 prefix "A:B:C:D:E:F:G:H/I". + route_map: + type: str + redistribute_routes: + type: list + primary_key: source_protocol + allow_duplicate_primary_key: true + items: + type: dict + keys: + source_protocol: + type: str + valid_values: + - connected + - isis + - ospf + - ospfv3 + - static + include_leaked: + type: bool + description: Only applicable if `source_protocol` is `isis`. route_map: type: str + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` takes + precedence. + + Only applicable if `source_protocol` is `isis`.' + ospf_route_type: + type: str + valid_values: + - external + - internal + - nssa-external + - nssa-external 1 + - nssa-external 2 + description: 'Routes learned by the OSPF protocol. + + The `ospf_route_type` is valid for source_protocols ''ospf'' and + ''ospfv3''. + + ' address_family_ipv6_sr_te: type: dict keys: @@ -8723,10 +14438,10 @@ keys: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. peer_groups: type: list primary_key: name @@ -8735,15 +14450,15 @@ keys: keys: name: type: str - description: Peer-group name + description: Peer-group name. activate: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. address_family_link_state: type: dict keys: @@ -8773,7 +14488,7 @@ keys: keys: name: type: str - description: Peer-group name + description: Peer-group name. activate: type: bool missing_policy: @@ -8867,7 +14582,7 @@ keys: keys: name: type: str - description: Peer-group name + description: Peer-group name. activate: type: bool address_family_flow_spec_ipv6: @@ -8909,9 +14624,45 @@ keys: keys: name: type: str - description: Peer-group name + description: Peer-group name. + activate: + type: bool + address_family_path_selection: + type: dict + keys: + bgp: + type: dict + keys: + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths + neighbors: + type: list + primary_key: ip_address + items: + type: dict + keys: + ip_address: + type: str + activate: + type: bool + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths + peer_groups: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: Peer-group name. activate: type: bool + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths address_family_vpn_ipv4: type: dict keys: @@ -8925,15 +14676,37 @@ keys: keys: name: type: str - description: Peer-group name + description: Peer-group name. activate: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. + rcf_in: + type: str + description: 'Inbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + rcf_out: + type: str + description: 'Outbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + default_route: + type: dict + keys: + enabled: + type: bool + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg).' + route_map: + type: str route: type: dict keys: @@ -8953,10 +14726,32 @@ keys: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. + rcf_in: + type: str + description: 'Inbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + rcf_out: + type: str + description: 'Outbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + default_route: + type: dict + keys: + enabled: + type: bool + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg).' + route_map: + type: str neighbor_default_encapsulation_mpls_next_hop_self: type: dict keys: @@ -8975,15 +14770,37 @@ keys: keys: name: type: str - description: Peer-group name + description: Peer-group name. activate: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. + rcf_in: + type: str + description: 'Inbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + rcf_out: + type: str + description: 'Outbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + default_route: + type: dict + keys: + enabled: + type: bool + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg).' + route_map: + type: str route: type: dict keys: @@ -9003,10 +14820,32 @@ keys: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. + rcf_in: + type: str + description: 'Inbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + rcf_out: + type: str + description: 'Outbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + default_route: + type: dict + keys: + enabled: + type: bool + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg).' + route_map: + type: str neighbor_default_encapsulation_mpls_next_hop_self: type: dict keys: @@ -9020,24 +14859,84 @@ keys: keys: name: type: str - description: VRF name + description: VRF name. convert_types: - int + bgp: + type: dict + keys: + redistribute_internal: + type: bool + description: Allow redistribution of iBGP routes into an Interior + Gateway Protocol (IGP). EOS default is true. + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths + keys: + install: + type: bool + description: Install BGP backup path. + install_ecmp_primary: + type: bool + description: Allow additional path with ECMP primary path. rd: type: str - description: Route distinguisher + description: Route distinguisher. evpn_multicast: type: bool evpn_multicast_address_family: type: dict - description: Enable per-AF EVPN multicast settings + description: Enable per-AF EVPN multicast settings. keys: ipv4: type: dict keys: transit: type: bool - description: Enable EVPN multicast transit mode + description: Enable EVPN multicast transit mode. + evpn_multicast_gateway_dr_election: + type: dict + keys: + algorithm: + type: str + required: true + description: "DR election algorithms:\n hrw: Default selection + based on highest random weight.\n modulus: Selection based on + VLAN ID modulo number of candidates.\n preference: Selection + based on a configured preference value." + valid_values: + - hrw + - modulus + - preference + preference_value: + type: int + description: Required when `algorithm` is `preference`. + min: 0 + max: 65535 + convert_types: + - str + default_route_exports: + type: list + primary_key: address_family + description: Enable default-originate per VRF/address-family. + items: + type: dict + keys: + address_family: + type: str + valid_values: + - evpn + - vpn-ipv4 + - vpn-ipv6 + always: + type: bool + route_map: + type: str + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg).' route_targets: type: dict keys: @@ -9055,6 +14954,25 @@ keys: type: str route_map: type: str + description: Only applicable if `address_family` is one of + `evpn`, `vpn-ipv4` or `vpn-ipv6`. + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + Only applicable if `address_family` is one of `evpn`, `vpn-ipv4` + or `vpn-ipv6`.' + vpn_route_filter_rcf: + type: str + description: 'RCF function name with parenthesis for filtering + VPN routes. Also requires `rcf` to be set. + + Example: MyFunction(myarg). + + Only applicable if `address_family` is one of `vpn-ipv4` + or `vpn-ipv6`.' export: type: list primary_key: address_family @@ -9069,13 +14987,32 @@ keys: type: str route_map: type: str + description: Only applicable if `address_family` is one of + `evpn`, `vpn-ipv4` or `vpn-ipv6`. + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + Only applicable if `address_family` is one of `evpn`, `vpn-ipv4` + or `vpn-ipv6`.' + vpn_route_filter_rcf: + type: str + description: 'RCF function name with parenthesis for filtering + VPN routes. Also requires `rcf` to be set. + + Example: MyFunction(myarg). + + Only applicable if `address_family` is one of `vpn-ipv4` + or `vpn-ipv6`.' router_id: - description: in IP address format A.B.C.D + description: in IP address format A.B.C.D. type: str timers: type: str description: BGP Keepalive and Hold Timer values in seconds as string - "<0-3600> <0-3600>" + "<0-3600> <0-3600>". networks: type: list primary_key: prefix @@ -9084,7 +15021,7 @@ keys: keys: prefix: type: str - description: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I" + description: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I". route_map: type: str updates: @@ -9110,7 +15047,7 @@ keys: listen_ranges: type: list description: 'Improved "listen_ranges" data model to support multiple - listen ranges and additional filter capabilities + listen ranges and additional filter capabilities. ' items: @@ -9118,27 +15055,30 @@ keys: keys: prefix: type: str - description: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I" + description: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I". peer_id_include_router_id: type: bool - description: Include router ID as part of peer filter + description: Include router ID as part of peer filter. peer_group: type: str - description: Peer-group name + description: Peer-group name. peer_filter: type: str - description: 'Peer-filter name + description: 'Peer-filter name. note: `peer_filter`` or `remote_as` is required but mutually exclusive. - If both are defined, peer_filter takes precedence + If both are defined, peer_filter takes precedence. ' remote_as: type: str - description: BGP AS <1-4294967295> or AS number in asdot notation - <1-65535>.<0-65535> + description: 'BGP AS <1-4294967295> or AS number in asdot notation + "<1-65535>.<0-65535>". + + For asdot notation in YAML inputs, the value must be put in + quotes, to prevent it from being interpreted as a float number.' convert_types: - int neighbors: @@ -9151,11 +15091,14 @@ keys: type: str peer_group: type: str - description: Peer-group name + description: Peer-group name. remote_as: type: str - description: BGP AS <1-4294967295> or AS number in asdot notation - <1-65535>.<0-65535> + description: 'BGP AS <1-4294967295> or AS number in asdot notation + "<1-65535>.<0-65535>". + + For asdot notation in YAML inputs, the value must be put in + quotes, to prevent it from being interpreted as a float number.' convert_types: - int password: @@ -9164,7 +15107,7 @@ keys: type: bool remove_private_as: type: dict - description: Remove private AS numbers in outbound AS path + description: Remove private AS numbers in outbound AS path. keys: enabled: type: bool @@ -9187,20 +15130,23 @@ keys: - str local_as: type: str - description: BGP AS <1-4294967295> or AS number in asdot notation - <1-65535>.<0-65535> + description: 'BGP AS <1-4294967295> or AS number in asdot notation + "<1-65535>.<0-65535>". + + For asdot notation in YAML inputs, the value must be put in + quotes, to prevent it from being interpreted as a float number.' convert_types: - int as_path: type: dict - description: BGP AS-PATH options + description: BGP AS-PATH options. keys: remote_as_replace_out: type: bool - description: Replace AS number with local AS number + description: Replace AS number with local AS number. prepend_own_disabled: type: bool - description: Disable prepending own AS number to AS path + description: Disable prepending own AS number to AS path. description: type: str route_reflector_client: @@ -9209,17 +15155,46 @@ keys: type: int min: 1 max: 255 - description: Time-to-live in range of hops + description: Time-to-live in range of hops. next_hop_self: type: bool shutdown: type: bool bfd: type: bool + description: Enable BFD. + bfd_timers: + type: dict + description: 'Override default BFD timers. BFD must be enabled + with `bfd: true`.' + keys: + interval: + type: int + convert_types: + - str + min: 50 + max: 60000 + required: true + description: Interval in milliseconds. + min_rx: + type: int + convert_types: + - str + min: 50 + max: 60000 + required: true + description: Rate in milliseconds. + multiplier: + type: int + min: 3 + max: 50 + convert_types: + - str + required: true timers: type: str description: BGP Keepalive and Hold Timer values in seconds as - string "<0-3600> <0-3600>" + string "<0-3600> <0-3600>". rib_in_pre_policy_retain: type: dict keys: @@ -9230,7 +15205,7 @@ keys: send_community: type: str description: '''all'' or a combination of ''standard'', ''extended'', - ''large'' and ''link-bandwidth (w/options)''' + ''large'' and ''link-bandwidth (w/options)''.' maximum_routes: type: int convert_types: @@ -9243,7 +15218,7 @@ keys: issued (0 means never warn) or Percentage of maximum number of routes at which to warn ("<1-100> - percent") + percent"). ' maximum_routes_warning_only: @@ -9259,7 +15234,7 @@ keys: - str min: 1 max: 10 - description: Number of local ASNs allowed in a BGP update + description: Number of local ASNs allowed in a BGP update. default_originate: type: dict keys: @@ -9273,16 +15248,31 @@ keys: type: str route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths prefix_list_in: type: str - description: Inbound prefix-list name + description: Inbound prefix-list name. + deprecation: + warning: true + removed: true + new_key: router_bgp.vrfs[].address_family_ipv4.neighbors[].prefix_list_in + or router_bgp.vrfs[].address_family_ipv6.neighbors[].prefix_list_in + remove_in_version: 5.0.0 prefix_list_out: type: str - description: Outbound prefix-list name + description: Outbound prefix-list name. + deprecation: + warning: true + removed: true + new_key: router_bgp.vrfs[].address_family_ipv4.neighbors[].prefix_list_out + or router_bgp.vrfs[].address_family_ipv6.neighbors[].prefix_list_out + remove_in_version: 5.0.0 neighbor_interfaces: type: list primary_key: name @@ -9291,24 +15281,270 @@ keys: keys: name: type: str - description: Interface name + description: Interface name. remote_as: type: str - description: BGP AS <1-4294967295> or AS number in asdot notation - <1-65535>.<0-65535> + description: 'BGP AS <1-4294967295> or AS number in asdot notation + "<1-65535>.<0-65535>". + + For asdot notation in YAML inputs, the value must be put in + quotes, to prevent it from being interpreted as a float number.' convert_types: - int peer_group: type: str - description: Peer-group name + description: Peer-group name. peer_filter: type: str - description: Peer-filter name + description: Peer-filter name. description: type: str + redistribute: + type: dict + description: Redistribute routes in to BGP. + keys: + attached_host: + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + bgp: + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + connected: + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` + takes precedence.' + include_leaked: + description: Include following routes while redistributing. + type: bool + dynamic: + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` + takes precedence.' + isis: + type: dict + keys: + enabled: + type: bool + required: true + isis_level: + type: str + description: Redistribute IS-IS route level. + valid_values: + - level-1 + - level-2 + - level-1-2 + route_map: + type: str + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` + takes precedence.' + include_leaked: + description: Include following routes while redistributing. + type: bool + ospf: + type: dict + keys: + enabled: + type: bool + description: Redistribute OSPF routes. + match_external: + description: Redistribute OSPF routes learned from external + sources. + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + include_leaked: + description: Include following routes while redistributing. + type: bool + match_internal: + description: Redistribute OSPF routes learned from internal + sources. + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + include_leaked: + description: Include following routes while redistributing. + type: bool + match_nssa_external: + description: Redistribute OSPF routes learned from external + NSSA sources. + type: dict + keys: + enabled: + type: bool + required: true + nssa_type: + description: NSSA External Type Number. + type: int + convert_types: + - str + valid_values: + - 1 + - 2 + route_map: + type: str + include_leaked: + description: Include following routes while redistributing. + type: bool + route_map: + type: str + include_leaked: + description: Include following routes while redistributing. + type: bool + ospfv3: + type: dict + keys: + enabled: + type: bool + description: Redistribute OSPFv3 routes. + match_external: + description: Redistribute OSPFv3 routes learned from external + sources. + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + include_leaked: + description: Include following routes while redistributing. + type: bool + match_internal: + description: Redistribute OSPFv3 routes learned from internal + sources. + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + include_leaked: + description: Include following routes while redistributing. + type: bool + match_nssa_external: + description: Redistribute OSPFv3 routes learned from external + NSSA sources. + type: dict + keys: + enabled: + type: bool + required: true + nssa_type: + description: NSSA External Type Number. + type: int + convert_types: + - str + valid_values: + - 1 + - 2 + route_map: + type: str + include_leaked: + description: Include following routes while redistributing. + type: bool + route_map: + type: str + include_leaked: + description: Include following routes while redistributing. + type: bool + rip: + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + static: + type: dict + keys: + enabled: + type: bool + required: true + route_map: + type: str + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` + takes precedence.' + include_leaked: + type: bool + description: Include following routes while redistributing. + user: + type: dict + keys: + enabled: + type: bool + required: true + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` + takes precedence.' redistribute_routes: type: list primary_key: source_protocol + allow_duplicate_primary_key: true + deprecation: + warning: true + remove_in_version: 6.0.0 + new_key: redistribute items: type: dict keys: @@ -9318,6 +15554,31 @@ keys: type: str include_leaked: type: bool + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` takes + precedence. + + Only applicable if `source_protocol` is one of `connected`, + `dynamic`, `isis`, `static` and `user`.' + ospf_route_type: + type: str + valid_values: + - external + - internal + - nssa-external + - nssa-external 1 + - nssa-external 2 + description: 'Routes learned by the OSPF protocol. + + The `ospf_route_type` is valid for source_protocols ''ospf'' + and ''ospfv3''. + + ' aggregate_addresses: type: list primary_key: prefix @@ -9326,7 +15587,7 @@ keys: keys: prefix: type: str - description: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I" + description: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I". advertise_only: type: bool as_set: @@ -9360,36 +15621,18 @@ keys: - permit additional_paths: type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths keys: install: type: bool + description: Install BGP backup path. install_ecmp_primary: type: bool - receive: - type: bool - send: - type: dict - keys: - any: - type: bool - backup: - type: bool - ecmp: - type: bool - ecmp_limit: - type: int - description: Amount of ECMP paths to send - convert_types: - - str - min: 2 - max: 64 - limit: - type: int - description: Amount of paths to send - convert_types: - - str - min: 2 - max: 64 + description: Allow additional path with ECMP primary path. + redistribute_internal: + type: bool + description: Allow redistribution of iBGP routes into an Interior + Gateway Protocol (IGP). EOS default is true. neighbors: type: list primary_key: ip_address @@ -9402,10 +15645,26 @@ keys: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. + rcf_in: + type: str + description: 'Inbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + rcf_out: + type: str + description: 'Outbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + prefix_list_in: + type: str + description: Inbound prefix-list name. + prefix_list_out: + type: str + description: Outbound prefix-list name. next_hop: type: dict keys: @@ -9417,6 +15676,9 @@ keys: required: true originate: type: bool + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths networks: type: list primary_key: prefix @@ -9425,9 +15687,58 @@ keys: keys: prefix: type: str - description: IPv4 prefix "A.B.C.D/E" + description: IPv4 prefix "A.B.C.D/E". + route_map: + type: str + redistribute_routes: + type: list + primary_key: source_protocol + allow_duplicate_primary_key: true + items: + type: dict + keys: + source_protocol: + type: str + valid_values: + - attached-host + - bgp + - connected + - dynamic + - isis + - ospf + - ospfv3 + - rip + - static + - user route_map: type: str + include_leaked: + type: bool + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` + takes precedence. + + Only applicable if `source_protocol` is one of `connected`, + `dynamic`, `isis`, `static` and `user`.' + ospf_route_type: + type: str + valid_values: + - external + - internal + - nssa-external + - nssa-external 1 + - nssa-external 2 + description: 'Routes learned by the OSPF protocol. + + The `ospf_route_type` is valid for source_protocols ''ospf'' + and ''ospfv3''. + + ' address_family_ipv6: type: dict keys: @@ -9451,36 +15762,18 @@ keys: - permit additional_paths: type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths keys: install: type: bool + description: Install BGP backup path. install_ecmp_primary: type: bool - receive: - type: bool - send: - type: dict - keys: - any: - type: bool - backup: - type: bool - ecmp: - type: bool - ecmp_limit: - type: int - description: Amount of ECMP paths to send - convert_types: - - str - min: 2 - max: 64 - limit: - type: int - description: Amount of paths to send - convert_types: - - str - min: 2 - max: 64 + description: Allow additional path with ECMP primary path. + redistribute_internal: + type: bool + description: Allow redistribution of iBGP routes into an Interior + Gateway Protocol (IGP). EOS default is true. neighbors: type: list primary_key: ip_address @@ -9493,10 +15786,29 @@ keys: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. + rcf_in: + type: str + description: 'Inbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + rcf_out: + type: str + description: 'Outbound RCF function name with parenthesis. + + Example: MyFunction(myarg).' + prefix_list_in: + type: str + description: Inbound prefix-list name. + prefix_list_out: + type: str + description: Outbound prefix-list name. + additional_paths: + type: dict + $ref: eos_cli_config_gen#/$defs/bgp_additional_paths networks: type: list primary_key: prefix @@ -9505,9 +15817,56 @@ keys: keys: prefix: type: str - description: IPv6 prefix "A:B:C:D:E:F:G:H/I" + description: IPv6 prefix "A:B:C:D:E:F:G:H/I". + route_map: + type: str + redistribute_routes: + type: list + primary_key: source_protocol + allow_duplicate_primary_key: true + items: + type: dict + keys: + source_protocol: + type: str + valid_values: + - attached-host + - bgp + - connected + - dhcp + - dynamic + - isis + - ospfv3 + - static + - user route_map: type: str + include_leaked: + type: bool + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` + takes precedence. + + Only applicable if `source_protocol` is one of `connected`, + `dynamic`, `isis`, `static` and `user`.' + ospf_route_type: + type: str + valid_values: + - external + - internal + - nssa-external + - nssa-external 1 + - nssa-external 2 + description: 'Routes learned by the OSPF protocol. + + The `ospf_route_type` is valid for source_protocols ''ospfv3''. + + ' address_family_ipv4_multicast: type: dict keys: @@ -9546,10 +15905,15 @@ keys: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. + additional_paths: + type: dict + keys: + receive: + type: bool networks: type: list primary_key: prefix @@ -9558,9 +15922,54 @@ keys: keys: prefix: type: str - description: IPv6 prefix "A.B.C.D/E" + description: IPv6 prefix "A.B.C.D/E". + route_map: + type: str + redistribute_routes: + type: list + primary_key: source_protocol + allow_duplicate_primary_key: true + items: + type: dict + keys: + source_protocol: + type: str + valid_values: + - attached-host + - connected + - isis + - ospf + - ospfv3 + - static route_map: type: str + include_leaked: + type: bool + description: Only applicable if `source_protocol` is `isis`. + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` + takes precedence. + + Only applicable if `source_protocol` is `isis`.' + ospf_route_type: + type: str + valid_values: + - external + - internal + - nssa-external + - nssa-external 1 + - nssa-external 2 + description: 'Routes learned by the OSPF protocol. + + The `ospf_route_type` is valid for source_protocols ''ospf'' + and ''ospfv3''. + + ' address_family_ipv6_multicast: type: dict keys: @@ -9599,10 +16008,15 @@ keys: type: bool route_map_in: type: str - description: Inbound route-map name + description: Inbound route-map name. route_map_out: type: str - description: Outbound route-map name + description: Outbound route-map name. + additional_paths: + type: dict + keys: + receive: + type: bool networks: type: list primary_key: prefix @@ -9611,9 +16025,53 @@ keys: keys: prefix: type: str - description: IPv6 prefix "A:B:C:D:E:F:G:H/I" + description: IPv6 prefix "A:B:C:D:E:F:G:H/I". route_map: type: str + redistribute_routes: + type: list + primary_key: source_protocol + allow_duplicate_primary_key: true + items: + type: dict + keys: + source_protocol: + type: str + valid_values: + - connected + - isis + - ospf + - ospfv3 + - static + route_map: + type: str + include_leaked: + type: bool + description: Only applicable if `source_protocol` is `isis`. + rcf: + type: str + description: 'RCF function name with parenthesis. + + Example: MyFunction(myarg). + + `route_map` and `rcf` are mutually exclusive. `route_map` + takes precedence. + + Only applicable if `source_protocol` is `isis`.' + ospf_route_type: + type: str + valid_values: + - external + - internal + - nssa-external + - nssa-external 1 + - nssa-external 2 + description: 'Routes learned by the OSPF protocol. + + The `ospf_route_type` is valid for source_protocols ''ospf'' + and ''ospfv3''. + + ' address_family_flow_spec_ipv4: type: dict keys: @@ -9676,89 +16134,20 @@ keys: type: str activate: type: bool + eos_cli: + type: str + description: 'Multiline EOS CLI rendered directly on the Router BGP, + VRF definition in the final EOS configuration. + + ' address_families: type: list primary_key: address_family deprecation: warning: true + removed: true new_key: address_family_* - remove_in_version: v5.0.0 - items: - type: dict - keys: - address_family: - type: str - bgp: - type: dict - keys: - missing_policy: - type: dict - keys: - direction_in_action: - type: str - valid_values: - - deny - - deny-in-out - - permit - direction_out_action: - type: str - valid_values: - - deny - - deny-in-out - - permit - additional_paths: - type: list - items: - type: str - neighbors: - type: list - primary_key: ip_address - items: - type: dict - keys: - ip_address: - type: str - activate: - type: bool - route_map_in: - type: str - description: Inbound route-map name - route_map_out: - type: str - description: Outbound route-map name - peer_groups: - type: list - primary_key: name - items: - type: dict - keys: - name: - type: str - description: Peer-group name - activate: - type: bool - next_hop: - type: dict - keys: - address_family_ipv6_originate: - type: bool - networks: - type: list - primary_key: prefix - items: - type: dict - keys: - prefix: - type: str - description: IPv4 prefix "A.B.C.D/E" or IPv6 prefix "A:B:C:D:E:F:G:H/I" - route_map: - type: str - eos_cli: - type: str - description: 'Multiline EOS CLI rendered directly on the Router BGP, - VRF definition in the final EOS configuration - - ' + remove_in_version: 5.0.0 session_trackers: type: list primary_key: name @@ -9767,14 +16156,18 @@ keys: keys: name: type: str - description: Name of session tracker + description: Name of session tracker. recovery_delay: type: int - description: Recovery delay in seconds + description: Recovery delay in seconds. convert_types: - str min: 1 max: 3600 + eos_cli: + type: str + description: Multiline EOS CLI rendered directly on the Router BGP in the + final EOS configuration. router_general: type: dict display_name: Router General configuration @@ -9784,10 +16177,10 @@ keys: keys: ipv4: type: str - description: IPv4 Address + description: IPv4 Address. ipv6: type: str - description: IPv6 Address + description: IPv6 Address. nexthop_fast_failover: type: bool default: false @@ -9799,7 +16192,7 @@ keys: keys: name: type: str - description: Destination-VRF + description: Destination-VRF. convert_types: - int leak_routes: @@ -9813,7 +16206,7 @@ keys: - int subscribe_policy: type: str - description: Route-Map Policy + description: Route-Map Policy. routes: type: dict keys: @@ -9824,27 +16217,146 @@ keys: keys: name: type: str - description: Dynamic Prefix List Name + description: Dynamic Prefix List Name. + control_functions: + type: dict + description: 'Routing control functions (RCF) used to filter and update routes + from a peer or during redistributions. + + Warning: + + This configuration cannot be pushed with `eos_config_deploy_eapi`, because + of limitations in `arista.eos` and `ansible.netcommon` plugins. + + The configuration can be pushed via CloudVision with `eos_config_deploy_cvp` + or `cv_deploy`.' + keys: + code_units: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: Name of the code unit. + content: + type: str + required: true + description: "Content of route control function.\ne.g.\nfunction + ACCEPT_ALL() {\n return true;\n }\nEOF" router_igmp: type: dict display_name: Router IGMP Configuration keys: + host_proxy_match_mroute: + type: str + description: 'Specify conditions for sending IGMP joins for host-proxy. + + ''iif'' will enable igmp host-proxy to work in iif aware. + + ''all'' will enable igmp host-proxy to work in iif unaware mode (EOS default). + + ' + valid_values: + - all + - iif ssm_aware: type: bool + vrfs: + type: list + description: 'Configure IGMP in a VRF. + + VRF ''default'' is not supported in EOS, please see keys directly under + ''router_igmp''.' + primary_key: name + items: + type: dict + keys: + name: + type: str + description: VRF name. + host_proxy_match_mroute: + type: str + description: 'Specify conditions for sending IGMP joins for host-proxy. + + ''iif'' will enable igmp host-proxy to work in iif aware. + + ''all'' will enable igmp host-proxy to work in iif unaware mode (EOS + default). + + ' + valid_values: + - all + - iif + router_internet_exit: + type: dict + description: Internet-exit feature to configure internet bound service for virtual + topologies. + keys: + policies: + type: list + description: Internet-exit policy represent a policy which can be attached + to a virtual topology profile. + primary_key: name + items: + type: dict + keys: + name: + type: str + exit_groups: + type: list + description: The exit groups that are configured under a policy are + strictly ordered, meaning an exit group appearing first has more priority + than the exit group that follows it. + items: + type: dict + keys: + name: + type: str + exit_groups: + type: list + description: 'Exit groups represent a group of exit options (connections). + + Traffic flows are load balanced in a round robin fashion across all the + members (exits) of the exit-group.' + primary_key: name + items: + type: dict + keys: + name: + type: str + fib_default: + type: bool + description: Fib default exit indicates that the flows that select this + exit will follow the default route available in the VRF of the flow. + local_connections: + type: list + description: 'Local connections refer to connections configured under + the `router_service_insertion`. + + The service-insertion module reports the health of the connection + and the exit will qualify for use only when it is healthy.' + items: + type: dict + keys: + name: + type: str router_isis: type: dict keys: instance: type: str required: true - description: ISIS Instance Name + description: ISIS Instance Name. net: type: str - description: CLNS Address like "49.0001.0001.0000.0001.00" + description: CLNS Address like "49.0001.0001.0000.0001.00". router_id: type: str - description: IPv4 Address + description: IPv4 Address. is_type: + display_name: IS Type type: str valid_values: - level-1 @@ -9862,44 +16374,149 @@ keys: keys: protected_prefixes: type: bool - delay: - type: int - convert_types: - - str - default: 10000 - description: Delay in milliseconds. + delay: + type: int + convert_types: + - str + default: 10000 + description: Delay in milliseconds. + set_overload_bit: + type: dict + keys: + enabled: + type: bool + on_startup: + type: dict + keys: + delay: + type: int + convert_types: + - str + description: Number of seconds. + wait_for_bgp: + type: dict + keys: + enabled: + type: bool + timeout: + type: int + convert_types: + - str + description: Number of seconds. + authentication: + type: dict + keys: + both: + type: dict + description: Authentication settings for level-1 and level-2. 'both' takes + precedence over 'level_1' and 'level_2' settings. + keys: + key_type: + type: str + convert_types: + - int + valid_values: + - '0' + - '7' + - 8a + description: Configure authentication key type. + key: + type: str + description: Password string. `key_type` is required for this setting. + key_ids: + type: list + primary_key: id + items: + type: dict + keys: + id: + type: int + convert_types: + - str + required: true + min: 1 + max: 65535 + description: Configure authentication key-id. + algorithm: + type: str + required: true + valid_values: + - sha-1 + - sha-224 + - sha-256 + - sha-384 + - sha-512 + key_type: + type: str + convert_types: + - int + required: true + valid_values: + - '0' + - '7' + - 8a + description: Configure authentication key type. + key: + type: str + required: true + description: Password string. + rfc_5310: + description: SHA digest computation according to rfc5310. + type: bool + mode: + type: str + description: Authentication mode. + valid_values: + - md5 + - sha + - text + - shared-secret + sha: + type: dict + description: Required settings for authentication mode 'sha'. + keys: + key_id: + type: int + convert_types: + - str + required: true + min: 1 + max: 65535 + shared_secret: + type: dict + description: Required settings for authentication mode 'shared_secret'. + keys: + profile: + type: str + required: true + algorithm: + type: str + required: true + valid_values: + - md5 + - sha-1 + - sha-224 + - sha-256 + - sha-384 + - sha-512 + rx_disabled: + type: bool + description: Disable authentication check on the receive side. + level_1: + type: dict + description: Authentication settings for level-1. 'both' takes precedence + over 'level_1' and 'level_2' settings. + $ref: eos_cli_config_gen#/keys/router_isis/keys/authentication/keys/both + level_2: + type: dict + description: Authentication settings for level-2. 'both' takes precedence + over 'level_1' and 'level_2' settings. + $ref: eos_cli_config_gen#/keys/router_isis/keys/authentication/keys/both advertise: type: dict keys: passive_only: type: bool - address_family: - type: list - items: - type: str - valid_values: - - ipv4 - - ipv6 - - ipv4 unicast - - ipv6 unicast - description: Address Family - deprecation: - warning: true - new_key: address_family_ipv4.enabled or address_family_ipv6.enabled - remove_in_version: 5.0.0 - isis_af_defaults: - type: list - items: - type: str - description: 'EOS CLI rendered under the address families - - Example "maximum-paths 64" - - ' - deprecation: - warning: true - new_key: address_family_ipv4/address_family_ipv6 - remove_in_version: 5.0.0 redistribute_routes: type: list items: @@ -9917,7 +16534,7 @@ keys: - static route_map: type: str - description: Route-map name + description: Route-map name. include_leaked: type: bool ospf_route_type: @@ -9927,18 +16544,22 @@ keys: - internal - nssa-external description: ospf_route_type is required with source_protocols 'ospf' - and 'ospfv3' + and 'ospfv3'. address_family_ipv4: type: dict keys: enabled: type: bool + required: true maximum_paths: type: int convert_types: - str min: 1 max: 128 + bfd_all_interfaces: + type: bool + description: Enable BFD on all interfaces. fast_reroute_ti_lfa: type: dict keys: @@ -9954,7 +16575,7 @@ keys: - level-2 srlg: type: dict - description: Shared Risk Link Group + description: Shared Risk Link Group. keys: enable: type: bool @@ -9967,18 +16588,22 @@ keys: type: bool rcf: type: str - description: Route Control Function + description: Route Control Function. address_family_ipv6: type: dict keys: enabled: type: bool + required: true maximum_paths: type: int convert_types: - str min: 1 max: 128 + bfd_all_interfaces: + type: bool + description: Enable BFD on all interfaces. fast_reroute_ti_lfa: type: dict keys: @@ -9992,10 +16617,10 @@ keys: valid_values: - level-1 - level-2 - description: Optional, default is to protect all levels + description: Optional, default is to protect all levels. srlg: type: dict - description: Shared Risk Link Group + description: Shared Risk Link Group. keys: enable: type: bool @@ -10019,6 +16644,85 @@ keys: type: int convert_types: - str + spf_interval: + type: dict + keys: + interval: + type: int + convert_types: + - str + description: 'Maximum interval between two SPFs in seconds or milliseconds. + + Range in seconds: <1-300> + + Range in milliseconds: <1-300000>' + interval_unit: + type: str + valid_values: + - seconds + - milliseconds + description: If interval unit is not defined EOS takes `seconds` by default. + wait_interval: + type: int + convert_types: + - str + min: 1 + max: 300000 + description: Initial wait interval for SPF in milliseconds. + hold_interval: + type: int + convert_types: + - str + min: 1 + max: 300000 + description: Hold interval between the first and second SPF runs in milliseconds. + graceful_restart: + type: dict + keys: + enabled: + type: bool + restart_hold_time: + type: int + convert_types: + - str + min: 5 + max: 300 + description: Number of seconds. + t2: + type: dict + keys: + level_1_wait_time: + type: int + convert_types: + - str + min: 5 + max: 300 + description: Level-1 LSP database sync wait time in seconds. + level_2_wait_time: + type: int + convert_types: + - str + min: 5 + max: 300 + description: Level-2 LSP database sync wait time in seconds. + eos_cli: + type: str + description: Multiline EOS CLI rendered directly on the router isis in the + final EOS configuration. + address_family: + type: list + deprecation: + removed: true + warning: true + new_key: address_family_ipv4.enabled or address_family_ipv6.enabled + remove_in_version: 5.0.0 + isis_af_defaults: + type: list + deprecation: + removed: true + warning: true + new_key: address_family_ipv4/address_family_ipv6 + remove_in_version: 5.0.0 router_l2_vpn: type: dict keys: @@ -10040,8 +16744,8 @@ keys: keys: prefix_list: type: str - description: Prefix-list name. ND Proxying is disabled for IPv6 addresses - defined in the prefix-list. + description: Prefix-list name. Neighbor Discovery Proxying is disabled + for IPv6 addresses defined in the prefix-list. nd_rs_flooding_disabled: type: bool virtual_router_nd_ra_flooding_disabled: @@ -10051,12 +16755,12 @@ keys: keys: originator_id_local_interface: type: str - description: Interface to use for originator ID + description: Interface to use for originator ID. rejected_limit: type: int convert_types: - str - description: Maximum number of rejected SA messages allowed in cache + description: Maximum number of rejected SA messages allowed in cache. min: 0 max: 40000 forward_register_packets: @@ -10075,12 +16779,12 @@ keys: keys: source_prefix: type: str - description: Source address prefix + description: Source address prefix. limit: type: int convert_types: - str - description: Limit for SAs matching the source address prefix + description: Limit for SAs matching the source address prefix. min: 0 max: 40000 required: true @@ -10092,7 +16796,7 @@ keys: keys: ipv4_address: type: str - description: Peer IP Address + description: Peer IP Address. default_peer: type: dict keys: @@ -10100,19 +16804,19 @@ keys: type: bool prefix_list: type: str - description: Prefix list to filter source of SA messages + description: Prefix list to filter source of SA messages. local_interface: type: str description: type: str disabled: type: bool - description: Disable the MSDP peer + description: Disable the MSDP peer. sa_limit: type: int convert_types: - str - description: Maximum number of SA messages allowed in cache + description: Maximum number of SA messages allowed in cache. min: 0 max: 40000 mesh_groups: @@ -10123,7 +16827,7 @@ keys: keys: name: type: str - description: Mesh group name + description: Mesh group name. keepalive: type: dict keys: @@ -10139,7 +16843,7 @@ keys: convert_types: - str required: true - description: Must be greater than keepalive timer + description: Must be greater than keepalive timer. min: 1 max: 65535 sa_filter: @@ -10147,10 +16851,10 @@ keys: keys: in_list: type: str - description: ACL to filter inbound SA messages + description: ACL to filter inbound SA messages. out_list: type: str - description: ACL to filter outbound SA messages + description: ACL to filter outbound SA messages. vrfs: type: list primary_key: name @@ -10159,17 +16863,17 @@ keys: keys: name: type: str - description: VRF name + description: VRF name. convert_types: - int originator_id_local_interface: type: str - description: Interface to use for originator ID + description: Interface to use for originator ID. rejected_limit: type: int convert_types: - str - description: Maximum number of rejected SA messages allowed in cache + description: Maximum number of rejected SA messages allowed in cache. min: 0 max: 40000 forward_register_packets: @@ -10188,12 +16892,12 @@ keys: keys: source_prefix: type: str - description: Source address prefix + description: Source address prefix. limit: type: int convert_types: - str - description: Limit for SAs matching the source address prefix + description: Limit for SAs matching the source address prefix. min: 0 max: 40000 required: true @@ -10205,7 +16909,7 @@ keys: keys: ipv4_address: type: str - description: Peer IP Address + description: Peer IP Address. default_peer: type: dict keys: @@ -10213,19 +16917,19 @@ keys: type: bool prefix_list: type: str - description: Prefix list to filter source of SA messages + description: Prefix list to filter source of SA messages. local_interface: type: str description: type: str disabled: type: bool - description: Disable the MSDP peer + description: Disable the MSDP peer. sa_limit: type: int convert_types: - str - description: Maximum number of SA messages allowed in cache + description: Maximum number of SA messages allowed in cache. min: 0 max: 40000 mesh_groups: @@ -10236,7 +16940,7 @@ keys: keys: name: type: str - description: Mesh group name + description: Mesh group name. keepalive: type: dict keys: @@ -10252,7 +16956,7 @@ keys: convert_types: - str required: true - description: Must be greater than keepalive timer + description: Must be greater than keepalive timer. min: 1 max: 65535 sa_filter: @@ -10260,21 +16964,28 @@ keys: keys: in_list: type: str - description: ACL to filter inbound SA messages + description: ACL to filter inbound SA messages. out_list: type: str - description: ACL to filter outbound SA messages + description: ACL to filter outbound SA messages. router_multicast: type: dict keys: ipv4: type: dict keys: + activity_polling_interval: + type: int + convert_types: + - str + min: 1 + max: 60 + description: MFIB entry activity polling interval. counters: type: dict keys: rate_period_decay: - description: Rate in seconds + description: Rate in seconds. type: int min: 0 max: 600 @@ -10303,7 +17014,7 @@ keys: type: dict keys: source_prefix: - description: Source address A.B.C.D or Source prefix A.B.C.D/E + description: Source address A.B.C.D or Source prefix A.B.C.D/E. type: str required: true destinations: @@ -10313,16 +17024,26 @@ keys: type: dict keys: nexthop: - description: Next-hop IP address or interface name + description: Next-hop IP address or interface name. type: str required: true distance: - description: Administrative distance for this route + description: Administrative distance for this route. type: int min: 1 max: 255 convert_types: - str + ipv6: + type: dict + keys: + activity_polling_interval: + type: int + convert_types: + - str + min: 1 + max: 60 + description: MFIB entry activity polling interval. vrfs: type: list primary_key: name @@ -10352,17 +17073,17 @@ keys: type: int convert_types: - str - description: OSPF Process ID + description: OSPF Process ID. vrf: type: str - description: VRF Name for OSPF Process + description: VRF Name for OSPF Process. convert_types: - int passive_interface_default: type: bool router_id: type: str - description: IPv4 Address + description: IPv4 Address. distance: type: dict keys: @@ -10404,7 +17125,7 @@ keys: type: list items: type: str - description: Interface Name + description: Interface Name. distribute_list_in: type: dict keys: @@ -10425,7 +17146,7 @@ keys: convert_types: - str description: Min interval in msecs between accepting the same - LSA + LSA. min: 0 max: 600000 tx_delay: @@ -10436,7 +17157,7 @@ keys: convert_types: - str description: Delay to generate first occurrence of LSA in - msecs + msecs. min: 0 max: 600000 min: @@ -10444,7 +17165,7 @@ keys: convert_types: - str description: Min delay between originating the same LSA - in msecs + in msecs. min: 1 max: 600000 max: @@ -10452,7 +17173,7 @@ keys: convert_types: - str description: 1-600000 Maximum delay between originating - the same LSA in msec + the same LSA in msec. min: 1 max: 600000 spf_delay: @@ -10462,21 +17183,21 @@ keys: type: int convert_types: - str - description: Initial SPF schedule delay in msecs + description: Initial SPF schedule delay in msecs. min: 0 max: 600000 min: type: int convert_types: - str - description: Min Hold time between two SPFs in msecs + description: Min Hold time between two SPFs in msecs. min: 0 max: 65535000 max: type: int convert_types: - str - description: Max wait time between two SPFs in msecs + description: Max wait time between two SPFs in msecs. min: 0 max: 65535000 default_information_originate: @@ -10488,7 +17209,7 @@ keys: type: int convert_types: - str - description: Metric for default route + description: Metric for default route. min: 1 max: 65535 metric_type: @@ -10498,7 +17219,7 @@ keys: valid_values: - 1 - 2 - description: OSPF metric type for default route + description: OSPF metric type for default route. summary_addresses: type: list primary_key: prefix @@ -10507,7 +17228,7 @@ keys: keys: prefix: type: str - description: Summary Prefix Address + description: Summary Prefix Address. tag: type: int attribute_map: @@ -10520,32 +17241,41 @@ keys: static: type: dict keys: + enabled: + type: bool + required: true route_map: type: str - description: Route Map Name + description: Route Map Name. include_leaked: type: bool connected: type: dict keys: + enabled: + type: bool + required: true route_map: type: str - description: Route Map Name + description: Route Map Name. include_leaked: type: bool bgp: type: dict keys: + enabled: + type: bool + required: true route_map: type: str - description: Route Map Name + description: Route Map Name. include_leaked: type: bool auto_cost_reference_bandwidth: type: int convert_types: - str - description: Bandwidth in mbps + description: Bandwidth in mbps. areas: type: list primary_key: id @@ -10563,10 +17293,10 @@ keys: type: list items: type: str - description: IPv4 Prefix + description: IPv4 Prefix. prefix_list: type: str - description: Prefix-List Name + description: Prefix-List Name. type: type: str valid_values: @@ -10585,7 +17315,7 @@ keys: type: int convert_types: - str - description: Metric for default route + description: Metric for default route. min: 1 max: 65535 metric_type: @@ -10595,7 +17325,7 @@ keys: valid_values: - 1 - 2 - description: OSPF metric type for default route + description: OSPF metric type for default route. maximum_paths: type: int convert_types: @@ -10623,26 +17353,285 @@ keys: type: str convert_types: - int - description: '"wait-for-bgp" or Integer 5-86400 + description: '"wait-for-bgp" or Integer 5-86400. + + Example: "wait-for-bgp" Or "222" + + ' + summary_lsa: + type: dict + keys: + override_metric: + type: int + convert_types: + - str + min: 1 + max: 16777215 + mpls_ldp_sync_default: + type: bool + eos_cli: + type: str + description: Multiline EOS CLI rendered directly on the Router OSPF + process ID in the final EOS configuration. + router_path_selection: + type: dict + description: Dynamic path selection configuration. + keys: + peer_dynamic_source: + type: str + valid_values: + - stun + description: Source of dynamic peer discovery. + path_groups: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: Path group name. + id: + type: int + description: Path group ID. + convert_types: + - str + min: 1 + max: 65535 + ipsec_profile: + type: str + description: IPSec profile for the path group. + flow_assignment: + type: str + valid_values: + - lan + description: Flow assignment `lan` can not be configured in a path group + with dynamic peers. + local_interfaces: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: Local interface name. + pattern: ^(Port-Channel|Ethernet(\d+/)*)\d+(\.\d+)?$ + public_address: + type: str + description: Public IP assigned by NAT. + stun: + type: dict + keys: + server_profiles: + type: list + required: true + min_length: 1 + max_length: 12 + description: STUN server-profile names. + items: + type: str + local_ips: + type: list + primary_key: ip_address + items: + type: dict + keys: + ip_address: + type: str + public_address: + type: str + description: Public IP assigned by NAT. + stun: + type: dict + keys: + server_profiles: + type: list + required: true + min_length: 1 + max_length: 12 + description: STUN server-profile names. + items: + type: str + dynamic_peers: + type: dict + description: Flow assignment `lan` can not be configured in a path group + with dynamic peers. + keys: + enabled: + type: bool + description: Enable `peer dynamic`. + ip_local: + type: bool + description: Prefer local IP address. + ipsec: + type: bool + description: IPsec configuration for dynamic peers. + static_peers: + type: list + primary_key: router_ip + items: + type: dict + keys: + router_ip: + type: str + description: Peer router IP. + name: + type: str + description: Name of the site. + ipv4_addresses: + type: list + description: Static IPv4 addresses. + items: + type: str + keepalive: + type: dict + keys: + auto: + type: bool + description: Enable adaptive keepalive and feedback interval. + default: false + interval: + type: int + description: Interval in milliseconds. + min: 50 + max: 60000 + convert_types: + - str + failure_threshold: + type: int + min: 2 + max: 100 + description: Failure threshold in number of intervals. Required + when `interval` is set. + convert_types: + - str + load_balance_policies: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: Load-balance policy name. + lowest_hop_count: + type: bool + description: Prefer paths with lowest hop-count. + jitter: + type: int + description: Jitter requirement for this load balance policy in milliseconds. + convert_types: + - str + min: 0 + max: 10000 + latency: + type: int + description: One way delay requirement for this load balance policy + in milliseconds. + convert_types: + - str + min: 0 + max: 10000 + loss_rate: + type: str + description: 'Loss Rate requirement in percentage for this load balance + policy. + + Value between 0.00 and 100.00.' + convert_types: + - int + - float + pattern: ^\d+(\.\d{1,2})?$ + path_groups: + type: list + primary_key: name + description: List of path-groups to use for this load balance policy. + items: + type: dict + keys: + name: + type: str + description: Path-group name. + priority: + type: int + description: 'Priority for this path-group. + + The EOS default value is 1.' + convert_types: + - str + min: 1 + max: 65535 + policies: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: DPS policy name. + default_match: + type: dict + keys: + load_balance: + type: str + description: Name of the load-balance policy. + rules: + type: list + primary_key: id + items: + type: dict + keys: + id: + type: int + description: Rule ID. + convert_types: + - str + min: 1 + max: 255 + application_profile: + type: str + required: true + load_balance: + type: str + description: Name of the load-balance policy. + vrfs: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: VRF name. + path_selection_policy: + type: str + description: DPS policy name to use for this VRF. + tcp_mss_ceiling: + type: dict + keys: + ipv4_segment_size: + type: str + description: 'Segment Size for IPv4. - Example: "wait-for-bgp" Or "222" + Can be an integer in the range 64-65515 or "auto". - ' - summary_lsa: - type: dict - keys: - override_metric: - type: int - convert_types: - - str - min: 1 - max: 16777215 - mpls_ldp_sync_default: - type: bool - eos_cli: - type: str - description: Multiline EOS CLI rendered directly on the Router OSPF - process ID in the final EOS configuration + "auto" will enable auto-discovery which clamps the TCP MSS value to + the minimum of all the direct paths + + and multi-hop path MTU towards a remote VTEP (minus 40bytes to account + for IP + TCP header).' + convert_types: + - int + direction: + type: str + valid_values: + - ingress + default: ingress + description: 'Enforce on packets through DPS tunnel for a specific direction. + + Only ''ingress'' direction is supported.' router_pim_sparse_mode: type: dict keys: @@ -10651,19 +17640,20 @@ keys: keys: bfd: type: bool - description: Enable/Disable BFD + description: Enable/Disable BFD. ssm_range: type: str - description: IPv4 Prefix associated with SSM + description: IPv4 Prefix associated with SSM. rp_addresses: type: list primary_key: address + allow_duplicate_primary_key: true items: type: dict keys: address: type: str - description: RP Address + description: RP Address. groups: type: list items: @@ -10690,7 +17680,7 @@ keys: keys: address: type: str - description: Anycast RP Address + description: Anycast RP Address. other_anycast_rp_addresses: type: list primary_key: address @@ -10699,7 +17689,7 @@ keys: keys: address: type: str - description: Other Anycast RP Address + description: Other Anycast RP Address. register_count: type: int convert_types: @@ -10712,7 +17702,7 @@ keys: keys: name: type: str - description: VRF Name + description: VRF Name. convert_types: - int ipv4: @@ -10720,7 +17710,7 @@ keys: keys: bfd: type: bool - description: Enable/Disable BFD + description: Enable/Disable BFD. rp_addresses: type: list items: @@ -10728,7 +17718,7 @@ keys: keys: address: type: str - description: RP Address + description: RP Address. required: true groups: type: list @@ -10748,9 +17738,201 @@ keys: max: 32 override: type: bool + router_segment_security: + type: dict + keys: + enabled: + type: bool + policies: + type: list + description: 'Customised application policies. + + Using the Application Traffic Recognition L4 profiles, custom policies can + be defined. The built-in application ''app-match-all'' can be used to match + any packets. + + Note that this is stateless, so both the source and destination flows need + to be considered.' + primary_key: name + items: + type: dict + keys: + name: + type: str + description: Policy name. + sequence_numbers: + type: list + required: true + primary_key: sequence + items: + type: dict + keys: + sequence: + type: int + description: Sequence ID. + convert_types: + - str + min: 1 + max: 1023 + application: + type: str + required: true + description: The name of the application. + action: + type: str + required: true + description: The action to take - note that platform support for + the redirect action is limited. The "redirect" action also requires + the 'next_hop' to be configured. + valid_values: + - forward + - drop + - redirect + log: + type: bool + description: Enable logging - note that platform support is limited. + stateless: + type: bool + description: Take action, regardless of state. Should be set to + 'true' for MSS-G. + default: true + next_hop: + type: str + description: When the action is 'redirect', this indicates the + IPv4 next hop to redirect to. + vrfs: + type: list + description: The name of the VRF that the segments and policies are defined + in. + primary_key: name + items: + type: dict + keys: + name: + type: str + segments: + type: list + primary_key: name + required: true + items: + type: dict + keys: + name: + type: str + description: Segment name. + definition: + type: dict + keys: + interfaces: + type: list + description: The names of the source interface e.g. Port-Channel1 + - note that platform support is limited. + min_length: 1 + items: + type: str + match_lists: + type: list + description: The set of lists that define the segment. These + can be a mix of IPv4 and IPv6 prefix or match lists. + max_length: 2 + min_length: 1 + primary_key: address_family + items: + type: dict + keys: + address_family: + type: str + required: true + description: Indicate which address-family the match + list belongs to e.g. ipv4 or ipv6. + valid_values: + - ipv4 + - ipv6 + covered_prefix_list: + type: str + description: The name of the prefix-list. You can have + a maximum of one per address-family. Mutually exclusive + to the use of match_list. If both are configured + prefix takes precedence. + prefix: + type: str + description: The name of the match-list. You can have + a maximum of one per address-family. Mutually exclusive + to the use of covered_prefix_list. If both are configured + prefix takes precedence. + policies: + type: list + description: The policies controlling traffic into the segment. + primary_key: from + items: + type: dict + keys: + from: + type: str + description: The name of the source segment or 'forwarding-segments' + for all segments. + policy: + type: str + description: The name of the policy to apply. The built-in + policies are 'policy-forward-all' and 'policy-drop-all'. + fallback_policy: + type: str + description: Only supported on the R3 series platforms, this allows + a per-segment default policy to be specified by name. + router_service_insertion: + type: dict + description: Configure network services inserted to data forwarding. + keys: + enabled: + type: bool + connections: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: Connection name. + ethernet_interface: + type: dict + description: 'Outgoing physical interface or subinterface to use for + the connection. + + If both `ethernet_interface` and `tunnel_interface` are configured, + `ethernet_interface` will be used.' + keys: + name: + type: str + required: true + description: e.g. Ethernet2 or Ethernet2/2.2 + next_hop: + type: str + required: true + description: Next-hop IPv4 address (without mask). + tunnel_interface: + type: dict + description: 'Outgoing tunnel interface(s) to use for this connection. + + If both `ethernet_interface` and `tunnel_interface` are configured, + `ethernet_interface` will be used.' + keys: + primary: + type: str + description: e.g. Tunnel2 + secondary: + type: str + description: e.g. Tunnel3 + monitor_connectivity_host: + type: str + description: Name of the host defined under `monitor_connectivity.hosts` + used to derive the health of the connection. router_traffic_engineering: type: dict keys: + enabled: + type: bool + required: true router_id: type: dict keys: @@ -10770,7 +17952,7 @@ keys: keys: address: type: str - description: IPv4 or IPv6 address + description: IPv4 or IPv6 address. colors: type: list primary_key: value @@ -10791,7 +17973,7 @@ keys: type: str sbfd_remote_discriminator: type: str - description: IPv4 address or 32 bit integer + description: IPv4 address or 32 bit integer. convert_types: - int path_group: @@ -10856,13 +18038,17 @@ keys: type: int convert_types: - str + sample_input_subinterface: + type: bool + sample_output_subinterface: + type: bool dangerous: type: bool polling_interval: type: int convert_types: - str - description: Polling interval in seconds + description: Polling interval in seconds. vrfs: type: list primary_key: name @@ -10881,7 +18067,7 @@ keys: keys: destination: type: str - description: Sflow Destination IP Address + description: Sflow Destination IP Address. port: type: int description: Port Number @@ -10897,7 +18083,7 @@ keys: ' source_interface: type: str - description: Source Interface + description: Source Interface. destinations: type: list primary_key: destination @@ -10906,10 +18092,10 @@ keys: keys: destination: type: str - description: Sflow Destination IP Address + description: Sflow Destination IP Address. port: type: int - description: Port Number + description: Port Number. convert_types: - str source: @@ -10922,7 +18108,7 @@ keys: ' source_interface: type: str - description: Source Interface + description: Source Interface. extensions: type: list primary_key: name @@ -10931,10 +18117,10 @@ keys: keys: name: type: str - description: Extension Name + description: Extension Name. enabled: type: bool - description: Enable or Disable Extension + description: Enable or Disable Extension. required: true interface: type: dict @@ -10983,7 +18169,7 @@ keys: default: true snmp_server: type: dict - description: SNMP settings + description: SNMP settings. keys: engine_ids: type: dict @@ -10992,7 +18178,7 @@ keys: type: str convert_types: - int - description: 'Engine ID in hexadecimal + description: 'Engine ID in hexadecimal. ' remotes: @@ -11004,12 +18190,12 @@ keys: type: str convert_types: - int - description: 'Remote engine ID in hexadecimal + description: 'Remote engine ID in hexadecimal. ' address: type: str - description: 'Hostname or IP of remote engine + description: 'Hostname or IP of remote engine. ' udp_port: @@ -11018,10 +18204,10 @@ keys: - str contact: type: str - description: SNMP contact + description: SNMP contact. location: type: str - description: SNMP location + description: SNMP location. communities: type: list primary_key: name @@ -11030,7 +18216,7 @@ keys: keys: name: type: str - description: Community name + description: Community name. access: type: str valid_values: @@ -11041,13 +18227,13 @@ keys: keys: name: type: str - description: IPv4 access list name + description: IPv4 access list name. access_list_ipv6: type: dict keys: name: type: str - description: IPv6 access list name + description: IPv6 access list name. view: type: str ipv4_acls: @@ -11057,7 +18243,7 @@ keys: keys: name: type: str - description: IPv4 access list name + description: IPv4 access list name. vrf: type: str convert_types: @@ -11069,7 +18255,7 @@ keys: keys: name: type: str - description: IPv6 access list name + description: IPv6 access list name. vrf: type: str convert_types: @@ -11082,7 +18268,7 @@ keys: keys: name: type: str - description: Interface name + description: Interface name. vrf: type: str convert_types: @@ -11094,7 +18280,7 @@ keys: keys: name: type: str - description: SNMP view name + description: SNMP view name. mib_family_name: type: str included: @@ -11102,6 +18288,7 @@ keys: MIB_family_name: deprecation: warning: true + removed: true remove_in_version: 5.0.0 new_key: mib_family_name type: str @@ -11112,7 +18299,7 @@ keys: keys: name: type: str - description: Group name + description: Group name. version: type: str valid_values: @@ -11127,13 +18314,13 @@ keys: - priv read: type: str - description: Read view + description: Read view. write: type: str - description: Write view + description: Write view. notify: type: str - description: Notify view + description: Notify view. users: type: list items: @@ -11141,22 +18328,22 @@ keys: keys: name: type: str - description: Username + description: Username. group: type: str - description: Group name + description: Group name. remote_address: type: str - description: 'Hostname or ip of remote engine + description: 'Hostname or ip of remote engine. - The remote_address and udp_port are used for remote users + The remote_address and udp_port are used for remote users. ' udp_port: type: int convert_types: - str - description: 'udp_port will not be used if no remote_address is configured + description: 'udp_port will not be used if no remote_address is configured. ' version: @@ -11169,29 +18356,29 @@ keys: type: str convert_types: - int - description: 'Engine ID in hexadecimal for localizing auth and/or priv + description: 'Engine ID in hexadecimal for localizing auth and/or priv. ' auth: type: str - description: 'Hash algorithm + description: 'Hash algorithm. ' auth_passphrase: type: str description: 'Hashed authentication passphrase if localized is used - else cleartext authentication passphrase + else cleartext authentication passphrase. ' priv: type: str - description: 'Encryption algorithm + description: 'Encryption algorithm. ' priv_passphrase: type: str description: 'Hashed privacy passphrase if localized is used else cleartext - privacy passphrase + privacy passphrase. ' hosts: @@ -11201,7 +18388,7 @@ keys: keys: host: type: str - description: Host IP address or name + description: Host IP address or name. vrf: type: str convert_types: @@ -11216,7 +18403,7 @@ keys: - '3' community: type: str - description: Community name + description: Community name. users: type: list items: @@ -11236,7 +18423,7 @@ keys: enable: type: bool default: false - description: 'Enable or disable all snmp-traps + description: 'Enable or disable all snmp-traps. ' snmp_traps: @@ -11246,7 +18433,7 @@ keys: keys: name: type: str - description: 'Enable or disable specific snmp-traps and their sub_traps + description: 'Enable or disable specific snmp-traps and their sub_traps. Examples: @@ -11266,11 +18453,14 @@ keys: keys: name: type: str - description: VRF name + description: VRF name. convert_types: - int enable: type: bool + ifmib_ifspeed_shape_rate: + type: bool + description: SNMP ifspeed reflecting shaping rate. spanning_tree: type: dict keys: @@ -11299,7 +18489,7 @@ keys: type: int convert_types: - str - description: Maximum number of BPDUs per timer interval + description: Maximum number of BPDUs per timer interval. rstp_priority: type: int convert_types: @@ -11318,7 +18508,7 @@ keys: type: int convert_types: - str - description: 0-65535 + description: 0-65535. instances: type: list primary_key: id @@ -11329,7 +18519,7 @@ keys: type: int convert_types: - str - description: Instance ID + description: Instance ID. vlans: type: str convert_types: @@ -11349,7 +18539,7 @@ keys: type: str convert_types: - int - description: Instance ID + description: Instance ID. priority: type: int convert_types: @@ -11390,7 +18580,9 @@ keys: keys: name: type: str - description: Access-list Name + description: Access-list Name. + convert_types: + - int counters_per_entry: type: bool sequence_numbers: @@ -11402,15 +18594,17 @@ keys: keys: sequence: type: int - description: Sequence ID + description: Sequence ID. convert_types: - str action: type: str required: true - description: 'Action as string + description: 'Action as string. - Example: "deny ip any any"' + Example: "deny ip any any" + + ' static_routes: type: list items: @@ -11418,20 +18612,20 @@ keys: keys: vrf: type: str - description: VRF Name + description: VRF Name. convert_types: - int destination_address_prefix: type: str - description: IPv4_network/Mask + description: IPv4_network/Mask. interface: type: str gateway: type: str - description: IPv4 Address + description: IPv4 Address. track_bfd: type: bool - description: Track next-hop using BFD + description: Track next-hop using BFD. distance: type: int convert_types: @@ -11446,7 +18640,7 @@ keys: max: 4294967295 name: type: str - description: Description + description: Description. metric: type: int convert_types: @@ -11455,15 +18649,15 @@ keys: max: 4294967295 stun: type: dict - description: STUN configuration + description: STUN configuration. keys: client: type: dict - description: STUN client settings + description: STUN client settings. keys: server_profiles: type: list - description: List of server profiles for the client + description: List of server profiles for the client. primary_key: name items: type: dict @@ -11472,12 +18666,70 @@ keys: type: str ip_address: type: str + ssl_profile: + type: str + description: SSL profile name. + port: + type: int + description: Destination port for the request STUN server (default + - 3478). + min: 1 + max: 65535 + convert_types: + - str server: type: dict - description: STUN server settings + description: STUN server settings. keys: + local_interfaces: + type: list + min_length: 1 + items: + type: str + bindings_timeout: + type: int + description: Timeout for bindings stored on STUN server in seconds. + convert_types: + - str + min: 10 + max: 7200 + ssl_profile: + type: str + description: SSL profile name. + ssl_connection_lifetime: + type: dict + description: 'SSL connection lifetime in minutes or hours. + + If both are specified, minutes is given higher precedence.' + keys: + minutes: + type: int + description: SSL connection lifetime in minutes (default - 120). + convert_types: + - str + min: 1 + max: 1440 + hours: + type: int + description: SSL connection lifetime in hours (default - 2). + convert_types: + - str + min: 1 + max: 24 + port: + type: int + description: Listening port for STUN server (default - 3478). + min: 1 + max: 65535 + convert_types: + - str local_interface: type: str + deprecation: + removed: true + warning: true + new_key: local_interfaces + remove_in_version: v5.0.0 switchport_default: type: dict keys: @@ -11502,11 +18754,35 @@ keys: - untagged vlan: type: int - description: VLAN ID + description: VLAN ID. convert_types: - str min: 1 max: 4094 + switchport_port_security: + type: dict + keys: + mac_address: + type: dict + keys: + aging: + type: bool + moveable: + type: bool + persistence_disabled: + type: bool + violation_protect_chip_based: + type: bool + sync_e: + type: dict + keys: + network_option: + required: true + type: int + min: 1 + max: 2 + convert_types: + - str system: type: dict keys: @@ -11518,34 +18794,51 @@ keys: keys: ipv4: type: int - description: Segment size + description: Segment size. ipv6: type: int - description: Segment size + description: Segment size. ipv4_access_groups: type: list - primary_key: acl_name + unique_keys: + - vrf items: type: dict keys: acl_name: type: str + required: true vrf: type: str convert_types: - int ipv6_access_groups: type: list - primary_key: acl_name + unique_keys: + - vrf items: type: dict keys: acl_name: type: str + required: true vrf: type: str convert_types: - int + l1: + type: dict + keys: + unsupported_speed_action: + type: str + valid_values: + - error + - warn + unsupported_error_correction_action: + type: str + valid_values: + - error + - warn tacacs_servers: type: dict keys: @@ -11553,7 +18846,7 @@ keys: type: int convert_types: - str - description: Timeout in seconds + description: Timeout in seconds. min: 1 max: 1000 hosts: @@ -11563,14 +18856,14 @@ keys: keys: host: type: str - description: Host IP address or name + description: Host IP address or name. vrf: type: str convert_types: - int key: type: str - description: Encrypted key + description: Encrypted key. key_type: type: str convert_types: @@ -11586,7 +18879,7 @@ keys: type: int convert_types: - str - description: Timeout in seconds + description: Timeout in seconds. min: 1 max: 1000 policy_unknown_mandatory_attribute_ignore: @@ -11603,13 +18896,13 @@ keys: enabled: type: bool profile: - description: Profile Name + description: Profile Name. type: str no_errdisable: type: list items: type: str - description: Interface name e.g Ethernet1, Port-Channel1 + description: Interface name e.g Ethernet1, Port-Channel1. encapsulation_dot1br_strip: type: bool encapsulation_vn_tag_strip: @@ -11618,7 +18911,7 @@ keys: type: bool truncation_size: type: int - description: 'Allowed truncation_size values vary depending on the platform + description: 'Allowed truncation_size values vary depending on the platform. ' mac: @@ -11628,7 +18921,7 @@ keys: type: dict description: 'mac.timestamp.replace_source_mac and mac.timestamp.header.format are mutually exclsuive. If both are defined, replace_source_mac takes - precedence + precedence. ' keys: @@ -11643,14 +18936,14 @@ keys: - 48-bit - 64-bit eth_type: - description: EtherType + description: EtherType. type: int convert_types: - str fcs_append: type: bool description: 'mac.fcs_append and mac.fcs_error are mutually exclusive. - If both are defined, mac.fcs_append takes precedence + If both are defined, mac.fcs_append takes precedence. ' fcs_error: @@ -11665,7 +18958,7 @@ keys: keys: system: type: str - description: 'TCAM profile name to activate + description: 'TCAM profile name to activate. ' profiles: @@ -11676,7 +18969,7 @@ keys: keys: name: type: str - description: Tcam-Profile Name + description: Tcam-Profile Name. config: type: str required: false @@ -11689,8 +18982,10 @@ keys: source: type: str required: false - description: TCAM profile local source path. Used to read the TCAM profile - from a local path existing on the device. + description: 'TCAM profile local source path. Used to read the TCAM + profile from a local path existing on the device. + + ' terminal: type: dict display_name: Terminal Settings @@ -11711,15 +19006,15 @@ keys: keys: name: type: str - description: Name of tracker object + description: Name of tracker object. interface: type: str - description: Name of tracked interface + description: Name of tracked interface. required: true tracked_property: type: str default: line-protocol - description: Property to track + description: Property to track. traffic_policies: type: dict keys: @@ -11739,12 +19034,12 @@ keys: keys: name: type: str - description: IPv4 Prefix Field Set Name + description: IPv4 Prefix Field Set Name. prefixes: type: list items: type: str - description: IPv4 Prefix + description: IPv4 Prefix. ipv6: type: list primary_key: name @@ -11753,12 +19048,12 @@ keys: keys: name: type: str - description: IPv6 Prefix Field Set Name + description: IPv6 Prefix Field Set Name. prefixes: type: list items: type: str - description: IPv6 Prefix + description: IPv6 Prefix. ports: type: list primary_key: name @@ -11767,7 +19062,7 @@ keys: keys: name: type: str - description: L4 Port Field Set Name + description: L4 Port Field Set Name. port_range: type: str description: 'Example: ''10,20,80,440-450''' @@ -11779,7 +19074,7 @@ keys: keys: name: type: str - description: Traffic Policy Name + description: Traffic Policy Name. matches: type: list primary_key: name @@ -11788,12 +19083,13 @@ keys: keys: name: type: str - description: Traffic Policy Item + description: Traffic Policy Item. type: type: str valid_values: - ipv4 - ipv6 + required: true source: type: dict keys: @@ -11801,10 +19097,10 @@ keys: type: list items: type: str - description: IP address or prefix + description: IP address or prefix. prefix_lists: type: list - description: Field-set prefix lists + description: Field-set prefix lists. items: type: str destination: @@ -11814,27 +19110,27 @@ keys: type: list items: type: str - description: IP address or prefix + description: IP address or prefix. prefix_lists: type: list - description: Field-set prefix lists + description: Field-set prefix lists. items: type: str ttl: type: str - description: TTL range + description: TTL range. fragment: type: dict description: 'The ''fragment'' command is not supported when ''source port'' - or ''destination port'' command is configured + or ''destination port'' command is configured. ' keys: offset: type: str - description: Fragment offset range + description: Fragment offset range. protocols: type: list primary_key: protocol @@ -11845,16 +19141,16 @@ keys: type: str src_port: type: str - description: Port range + description: Port range. dst_port: type: str - description: Port range + description: Port range. src_field: type: str - description: L4 port range field set + description: L4 port range field set. dst_field: type: str - description: L4 port range field set + description: L4 port range field set. flags: type: list items: @@ -11866,6 +19162,10 @@ keys: type: list items: type: str + enforce_gtsm: + type: bool + description: Enforce the GTSM for BGP speakers. Only supported + when protocol is set to 'neighbors'. actions: type: dict keys: @@ -11877,15 +19177,15 @@ keys: type: int convert_types: - str - description: Traffic class ID + description: Traffic class ID. count: type: str - description: Counter name + description: Counter name. drop: type: bool log: type: bool - description: Only supported when action is set to drop + description: Only supported when action is set to drop. default_actions: type: dict keys: @@ -11900,15 +19200,15 @@ keys: type: int convert_types: - str - description: Traffic class ID + description: Traffic class ID. count: type: str - description: Counter name + description: Counter name. drop: type: bool log: type: bool - description: Only supported when action is set to drop + description: Only supported when action is set to drop. ipv6: type: dict keys: @@ -11920,15 +19220,23 @@ keys: type: int convert_types: - str - description: Traffic class ID + description: Traffic class ID. count: type: str - description: Counter name + description: Counter name. drop: type: bool log: type: bool - description: Only supported when action is set to drop + description: Only supported when action is set to drop. + transceiver_qsfp_default_mode_4x10: + type: bool + default: true + description: 'On all front panel ports which support this feature, the following + global configuration command changes the QSFP mode from 40G to 4x10G (default). + When set to false the command reverts the default QSFP mode back to 40G. + + ' tunnel_interfaces: type: list primary_key: name @@ -11937,7 +19245,7 @@ keys: keys: name: type: str - description: Tunnel Interface Name + description: Tunnel Interface Name. description: type: str shutdown: @@ -11950,44 +19258,49 @@ keys: - str vrf: type: str - description: VRF Name + description: VRF Name. + convert_types: + - int + underlay_vrf: + type: str + description: Underlay VRF Name. convert_types: - int ip_address: type: str format: ipv4_cidr - description: IPv4_address/Mask + description: IPv4_address/Mask. ipv6_enable: type: bool ipv6_address: type: str format: ipv6_cidr - description: IPv6_address/Mask + description: IPv6_address/Mask. access_group_in: - description: IPv4 ACL Name for ingress + description: IPv4 ACL Name for ingress. type: str access_group_out: - description: IPv4 ACL Name for egress + description: IPv4 ACL Name for egress. type: str ipv6_access_group_in: - description: IPv6 ACL Name for ingress + description: IPv6 ACL Name for ingress. type: str ipv6_access_group_out: - description: IPv6 ACL Name for egress + description: IPv6 ACL Name for egress. type: str tcp_mss_ceiling: type: dict keys: ipv4: type: int - description: Segment Size for IPv4 + description: Segment Size for IPv4. min: 64 max: 65495 convert_types: - str ipv6: type: int - description: Segment Size for IPv6 + description: Segment Size for IPv6. min: 64 max: 65475 convert_types: @@ -11998,22 +19311,42 @@ keys: - ingress - egress description: 'Optional direction (''ingress'', ''egress'') for tcp - mss ceiling + mss ceiling. ' + tunnel_mode: + type: str + valid_values: + - gre + - ipsec + description: 'Tunnel encapsulation method. + + `gre`: Generic route encapsulation protocol, + + `ipsec`: IPsec-over-IP encapsulation.' source_interface: type: str - description: Tunnel Source Interface Name + description: Tunnel Source Interface Name. destination: type: str - description: IPv4 or IPv6 Address Tunnel Destination + description: IPv4 or IPv6 Address Tunnel Destination. path_mtu_discovery: type: bool - description: Enable Path MTU Discovery On Tunnel + description: Enable Path MTU Discovery On Tunnel. + ipsec_profile: + type: str + description: 'Used only when `tunnel_mode` is set to `ipsec`. + + It must target a defined IPsec profile.' + nat_profile: + type: str + description: NAT interface profile. eos_cli: type: str - description: Multiline String with EOS CLI rendered directly on the Tunnel + description: 'Multiline String with EOS CLI rendered directly on the Tunnel interface in the final EOS configuration. + + ' virtual_source_nat_vrfs: type: list primary_key: name @@ -12022,12 +19355,12 @@ keys: keys: name: type: str - description: VRF Name + description: VRF Name. convert_types: - int ip_address: type: str - description: IPv4 Address + description: IPv4 Address. vlan_interfaces: type: list primary_key: name @@ -12036,21 +19369,29 @@ keys: keys: name: type: str - description: VLAN interface name like "Vlan123" + description: VLAN interface name like "Vlan123". description: type: str + logging: + type: dict + keys: + event: + type: dict + keys: + link_status: + type: bool shutdown: type: bool vrf: type: str - description: VRF name + description: VRF name. convert_types: - int arp_aging_timeout: type: int convert_types: - str - description: In seconds + description: In seconds. min: 1 max: 65535 arp_cache_dynamic_capacity: @@ -12069,25 +19410,30 @@ keys: type: bool ip_address: type: str - description: IPv4_address/Mask + description: IPv4_address/Mask. ip_address_secondaries: type: list items: type: str - description: IPv4_address/Mask + description: IPv4_address/Mask. ip_virtual_router_addresses: type: list items: type: str - description: IPv4 address or IPv4_address/Mask + description: IPv4 address or IPv4_address/Mask. ip_address_virtual: type: str - description: IPv4_address/Mask + description: IPv4_address/Mask. ip_address_virtual_secondaries: type: list items: type: str - description: IPv4_address/Mask + description: IPv4_address/Mask. + ip_verify_unicast_source_reachable_via: + type: str + valid_values: + - any + - rx ip_igmp: type: bool ip_igmp_version: @@ -12096,24 +19442,85 @@ keys: - str min: 1 max: 3 + ip_igmp_host_proxy: + type: dict + keys: + enabled: + type: bool + groups: + type: list + primary_key: group + items: + type: dict + keys: + group: + type: str + description: Multicast Address. + exclude: + type: list + primary_key: source + description: The same source must not be present both in `exclude` + and `include` list. + items: + type: dict + keys: + source: + type: str + include: + type: list + primary_key: source + description: The same source must not be present both in `exclude` + and `include` list. + items: + type: dict + keys: + source: + type: str + report_interval: + type: int + convert_types: + - str + min: 1 + max: 31744 + description: Time interval between unsolicited reports. + access_lists: + type: list + primary_key: name + description: Non-standard Access List name. + items: + type: dict + keys: + name: + type: str + version: + type: int + convert_types: + - str + min: 1 + max: 3 + description: IGMP version on IGMP host-proxy interface. ip_helpers: type: list - description: List of DHCP servers + description: List of DHCP servers. primary_key: ip_helper items: type: dict keys: ip_helper: type: str - description: IP address or hostname of DHCP server + description: IP address or hostname of DHCP server. source_interface: type: str - description: Interface used as source for forwarded DHCP packets + description: Interface used as source for forwarded DHCP packets. vrf: type: str - description: VRF where DHCP server can be reached + description: VRF where DHCP server can be reached. convert_types: - int + ip_dhcp_relay_all_subnets: + type: bool + description: Allow forwarding requests with secondary IP addresses in the + gateway address "giaddr" field. ip_nat: type: dict $ref: eos_cli_config_gen#/$defs/interface_ip_nat @@ -12121,50 +19528,52 @@ keys: type: bool ipv6_address: type: str - description: IPv6_address/Mask - ipv6_address_virtual: - type: str - description: 'IPv6_address/Mask - - If both "ipv6_address_virtual" and "ipv6_address_virtuals" are set, all - addresses will be configured - - ' - deprecation: - warning: true - new_key: ipv6_address_virtuals - remove_in_version: 5.0.0 + description: IPv6_address/Mask. ipv6_address_virtuals: type: list description: The new "ipv6_address_virtuals" key support multiple virtual ipv6 addresses. items: type: str - description: IPv6_address/Mask + description: IPv6_address/Mask. ipv6_address_link_local: type: str - description: IPv6_address/Mask - ipv6_virtual_router_address: - type: str - description: '"ipv6_virtual_router_address" should not be mixed with - - the new "ipv6_virtual_router_addresses" key below to avoid conflicts. - - ' - deprecation: - warning: true - remove_in_version: 5.0.0 - new_key: ipv6_virtual_router_addresses + description: IPv6_address/Mask. ipv6_virtual_router_addresses: type: list description: Improved "VARPv6" data model to support multiple VARPv6 addresses. items: type: str - description: IPv6 address or IPv6_address/Mask + description: IPv6 address or IPv6_address/Mask. ipv6_nd_ra_disabled: type: bool ipv6_nd_managed_config_flag: type: bool + ipv6_nd_other_config_flag: + type: bool + description: Set the "other stateful configuration" flag in IPv6 router + advertisements. + ipv6_nd_cache: + type: dict + description: IPv6 neighbor cache options. + keys: + dynamic_capacity: + type: int + description: Capacity of dynamic cache entries. + convert_types: + - str + min: 0 + max: 4294967295 + expire: + type: int + description: Cache entries expirery in seconds. + convert_types: + - str + min: 1 + max: 65535 + refresh_always: + type: bool + description: Force refresh on cache expiry. ipv6_nd_prefixes: type: list primary_key: ipv6_prefix @@ -12173,15 +19582,15 @@ keys: keys: ipv6_prefix: type: str - description: IPv6_address/Mask + description: IPv6_address/Mask. valid_lifetime: type: str - description: In seconds <0-4294967295> or infinite + description: In seconds <0-4294967295> or infinite. convert_types: - int preferred_lifetime: type: str - description: In seconds <0-4294967295> or infinite + description: In seconds <0-4294967295> or infinite. convert_types: - int no_autoconfig_flag: @@ -12194,7 +19603,7 @@ keys: keys: address: type: str - description: DHCP server's IPv6 address + description: DHCP server's IPv6 address. vrf: type: str convert_types: @@ -12202,27 +19611,39 @@ keys: local_interface: type: str description: Local interface to communicate with DHCP server - mutually - exclusive to source_address + exclusive to source_address. source_address: type: str description: Source IPv6 address to communicate with DHCP server - - mutually exclusive to local_interface + mutually exclusive to local_interface. link_address: type: str description: Override the default link address specified in the relayed - DHCP packet + DHCP packet. + ipv6_dhcp_relay_all_subnets: + type: bool + description: Allow forwarding requests with additional IPv6 addresses in + the gateway address "giaddr" field. access_group_in: type: str - description: IPv4 access-list name + description: IPv4 access-list name. + convert_types: + - int access_group_out: type: str - description: IPv4 access-list name + description: IPv4 access-list name. + convert_types: + - int ipv6_access_group_in: type: str - description: IPv6 access-list name + description: IPv6 access-list name. + convert_types: + - int ipv6_access_group_out: type: str - description: IPv6 access-list name + description: IPv6 access-list name. + convert_types: + - int multicast: type: dict keys: @@ -12232,7 +19653,7 @@ keys: boundaries: type: list description: Boundaries can be either 1 ACL or a list of multicast - IP address_range(s)/prefix but not combination of both + IP address_range(s)/prefix but not combination of both. primary_key: boundary items: type: dict @@ -12240,7 +19661,9 @@ keys: boundary: type: str description: IPv4 access-list name or IPv4 multicast group - prefix with mask + prefix with mask. + convert_types: + - int out: type: bool source_route_export: @@ -12263,7 +19686,7 @@ keys: boundaries: type: list description: Boundaries can be either 1 ACL or a list of multicast - IP address_range(s)/prefix but not combination of both + IP address_range(s)/prefix but not combination of both. primary_key: boundary items: type: dict @@ -12271,7 +19694,9 @@ keys: boundary: type: str description: IPv6 access-list name or IPv6 multicast group - prefix with mask + prefix with mask. + convert_types: + - int source_route_export: type: dict keys: @@ -12304,10 +19729,10 @@ keys: - message-digest ospf_authentication_key: type: str - description: Encrypted password used for simple authentication + description: Encrypted password used for simple authentication. ospf_message_digest_keys: type: list - description: Keys used for message-digest authentication + description: Keys used for message-digest authentication. primary_key: id items: type: dict @@ -12326,13 +19751,16 @@ keys: - sha512 key: type: str - description: Encrypted password + description: Encrypted password. pim: type: dict keys: ipv4: type: dict keys: + border_router: + type: bool + description: Configure PIM border router. EOS default is false. dr_priority: type: int convert_types: @@ -12343,9 +19771,35 @@ keys: type: bool local_interface: type: str + bfd: + type: bool + description: Set the default for whether Bidirectional Forwarding + Detection is enabled for PIM. + bidirectional: + type: bool + hello: + type: dict + keys: + count: + type: str + convert_types: + - int + - float + description: Number of missed hellos after which the neighbor + expires. Range <1.5-65535>. + interval: + type: int + convert_types: + - str + min: 1 + max: 65535 + description: PIM hello interval in seconds. isis_enable: type: str - description: ISIS instance name + description: ISIS instance name. + isis_bfd: + type: bool + description: Enable BFD for ISIS. isis_passive: type: bool isis_metric: @@ -12354,6 +19808,9 @@ keys: - str isis_network_point_to_point: type: bool + isis_authentication: + type: dict + $ref: eos_cli_config_gen#/keys/router_isis/keys/authentication mtu: type: int convert_types: @@ -12362,7 +19819,7 @@ keys: type: bool vrrp_ids: type: list - description: Improved "vrrp" data model to support multiple VRRP IDs + description: Improved "vrrp" data model to support multiple VRRP IDs. primary_key: id items: type: dict @@ -12371,12 +19828,14 @@ keys: type: int convert_types: - str - description: VRID + description: VRID. priority_level: type: int convert_types: - str - description: Instance priority + description: Instance priority. + min: 1 + max: 254 advertisement: type: dict keys: @@ -12384,7 +19843,9 @@ keys: type: int convert_types: - str - description: Interval in seconds + description: Interval in seconds. + min: 1 + max: 255 preempt: type: dict keys: @@ -12398,12 +19859,16 @@ keys: type: int convert_types: - str - description: Minimum preempt delay in seconds + description: Minimum preempt delay in seconds. + min: 0 + max: 3600 reload: type: int convert_types: - str - description: Reload preempt delay in seconds + description: Reload preempt delay in seconds. + min: 0 + max: 3600 timers: type: dict keys: @@ -12415,6 +19880,8 @@ keys: description: Delay after reload in seconds. convert_types: - str + min: 0 + max: 3600 tracked_object: type: list primary_key: name @@ -12423,14 +19890,14 @@ keys: keys: name: type: str - description: Tracked object name + description: Tracked object name. decrement: type: int convert_types: - str min: 1 max: 254 - description: Decrement VRRP priority by 1-254 + description: Decrement VRRP priority by 1-254. shutdown: type: bool ipv4: @@ -12439,7 +19906,7 @@ keys: address: type: str required: true - description: Virtual IPv4 address + description: Virtual IPv4 address. version: type: int convert_types: @@ -12453,41 +19920,20 @@ keys: address: type: str required: true - description: Virtual IPv6 address - vrrp: + description: Virtual IPv6 address. + ip_attached_host_route_export: type: dict - description: '"vrrp" should not be mixed with the new "vrrp_ids" key above - to avoid conflicts. - - ' - deprecation: - warning: true - remove_in_version: 5.0.0 - new_key: vrrp_ids keys: - virtual_router: - type: str - description: Virtual Router ID - priority: - type: int - convert_types: - - str - description: Instance priority - advertisement_interval: - type: int - convert_types: - - str - preempt_delay_minimum: + enabled: + type: bool + required: true + distance: type: int convert_types: - str - ipv4: - type: str - description: Virtual IPv4 address - ipv6: - type: str - description: Virtual IPv6 address - ip_attached_host_route_export: + min: 1 + max: 255 + ipv6_attached_host_route_export: type: dict keys: enabled: @@ -12499,6 +19945,14 @@ keys: - str min: 1 max: 255 + description: Administrative distance for generated routes. + prefix_length: + type: int + convert_types: + - str + min: 0 + max: 128 + description: Prefix length for generated routes. bfd: type: dict keys: @@ -12508,12 +19962,12 @@ keys: type: int convert_types: - str - description: Rate in milliseconds + description: Rate in milliseconds. min_rx: type: int convert_types: - str - description: Minimum RX hold time in milliseconds + description: Minimum RX hold time in milliseconds. multiplier: type: int convert_types: @@ -12528,25 +19982,49 @@ keys: keys: input: type: str - description: Name of policy-map used for policy based routing + description: Name of policy-map used for policy based routing. pvlan_mapping: type: str - description: List of VLANs as string + description: List of VLANs as string. tenant: type: str - description: Key only used for documentation or validation purposes + description: Key only used for documentation or validation purposes. tags: type: list items: type: str - description: Key only used for documentation or validation purposes + description: Key only used for documentation or validation purposes. type: type: str - description: Key only used for documentation or validation purposes + description: Key only used for documentation or validation purposes. eos_cli: type: str description: Multiline EOS CLI rendered directly on the VLAN interface in - the final EOS configuration + the final EOS configuration. + ipv6_address_virtual: + type: str + description: 'IPv6_address/Mask. + + ' + deprecation: + removed: true + warning: true + new_key: ipv6_address_virtuals + remove_in_version: 5.0.0 + ipv6_virtual_router_address: + type: str + deprecation: + removed: true + warning: true + remove_in_version: 5.0.0 + new_key: ipv6_virtual_router_addresses + vrrp: + type: dict + deprecation: + removed: true + warning: true + remove_in_version: 5.0.0 + new_key: vrrp_ids vlan_internal_order: type: dict keys: @@ -12586,10 +20064,10 @@ keys: type: int convert_types: - str - description: VLAN ID + description: VLAN ID. name: type: str - description: VLAN Name + description: VLAN Name. state: type: str valid_values: @@ -12599,7 +20077,7 @@ keys: type: list items: type: str - description: Trunk Group Name + description: Trunk Group Name. private_vlan: type: dict keys: @@ -12612,10 +20090,10 @@ keys: type: int convert_types: - str - description: Primary VLAN ID + description: Primary VLAN ID. tenant: type: str - description: Key only used for documentation or validation purposes + description: Key only used for documentation or validation purposes. vmtracer_sessions: type: list primary_key: name @@ -12624,14 +20102,14 @@ keys: keys: name: type: str - description: Vmtracer Session Name + description: Vmtracer Session Name. url: type: str username: type: str password: type: str - description: Type 7 Password Hash + description: Type 7 Password Hash. autovlan_disable: type: bool source_interface: @@ -12639,7 +20117,7 @@ keys: vrfs: type: list primary_key: name - description: 'These keys are ignored if the name of the vrf is ''default'' + description: 'These keys are ignored if the name of the vrf is ''default''. ' items: @@ -12647,7 +20125,7 @@ keys: keys: name: type: str - description: VRF Name + description: VRF Name. convert_types: - int description: @@ -12660,11 +20138,11 @@ keys: type: bool tenant: type: str - description: Key only used for documentation or validation purposes + description: Key only used for documentation or validation purposes. vxlan_interface: type: dict keys: - Vxlan1: + vxlan1: type: dict keys: description: @@ -12674,10 +20152,15 @@ keys: keys: source_interface: type: str - description: Source Interface Name + description: Source Interface Name. + multicast: + type: dict + keys: + headend_replication: + type: bool controller_client: type: dict - description: Client to CVX Controllers + description: Client to CVX Controllers. keys: enabled: type: bool @@ -12687,9 +20170,12 @@ keys: type: int convert_types: - str + vtep_to_vtep_bridging: + type: bool + description: Enable bridging between different VTEPs in vxlan overlay. virtual_router_encapsulation_mac_address: type: str - description: '"mlag-system-id" or ethernet_address (H.H.H) + description: '"mlag-system-id" or ethernet_address (H.H.H). ' bfd_vtep_evpn: @@ -12742,19 +20228,19 @@ keys: type: int convert_types: - str - description: VLAN ID + description: VLAN ID. vni: type: int convert_types: - str multicast_group: type: str - description: IP Multicast Group Address + description: IP Multicast Group Address. flood_vteps: type: list items: type: str - description: Remote VTEP IP Address + description: Remote VTEP IP Address. vrfs: type: list primary_key: name @@ -12763,7 +20249,7 @@ keys: keys: name: type: str - description: VRF Name + description: VRF Name. convert_types: - int vni: @@ -12772,19 +20258,203 @@ keys: - str multicast_group: type: str - description: IP Multicast Group Address + description: IP Multicast Group Address. flood_vteps: type: list items: type: str - description: Remote VTEP IP Address + description: Remote VTEP IP Address. flood_vtep_learned_data_plane: type: bool eos_cli: type: str - description: Multiline String with EOS CLI rendered directly on the Vxlan + description: 'Multiline String with EOS CLI rendered directly on the Vxlan interface in the final EOS configuration. + + ' + Vxlan1: + deprecation: + warning: true + remove_in_version: 6.0.0 + new_key: vxlan1 + type: dict + $ref: eos_cli_config_gen#/keys/vxlan_interface/keys/vxlan1 $defs: + application_traffic_recognition_application: + type: dict + keys: + protocols: + type: list + description: 'List of protocols to consider for this application. + + To use port field-sets (source, destination or both), the list + + must contain only one or two protocols, either `tcp` or `udp`. + + When using both protocols, one line is rendered for each in the configuration, + + hence the field-sets must have the same value for `tcp_src_port_set_name` + and + + `udp_src_port_set_name` and for `tcp_dest_port_set_name` and `udp_dest_port_set_name` + + if set in order to generate valid configuration in EOS.' + items: + type: str + valid_values: + - ahp + - esp + - icmp + - igmp + - ospf + - pim + - rsvp + - tcp + - udp + - vrrp + protocol_ranges: + type: list + description: 'Accept protocol value(s) or range(s). + + Protocol values can be between 1 and 255.' + items: + type: str + convert_types: + - int + udp_src_port_set_name: + type: str + description: 'Name of field set for UDP source ports. + + When the `protocols` list contain both `tcp` and `udp`, this key value + + must be the same as `tcp_src_port_set_name`.' + tcp_src_port_set_name: + type: str + description: 'Name of field set for TCP source ports. + + When the `protocols` list contain both `tcp` and `udp`, this key value + + must be the same as `udp_src_port_set_name`.' + udp_dest_port_set_name: + type: str + description: 'Name of field set for UDP destination ports. + + When the `protocols` list contain both `tcp` and `udp`, this key value + + must be the same as `tcp_dest_port_set_name`.' + tcp_dest_port_set_name: + type: str + description: 'Name of field set for TCP destination ports. + + When the `protocols` list contain both `tcp` and `udp`, this key value + + must be the same as `udp_dest_port_set_name`.' + bgp_additional_paths: + type: dict + keys: + receive: + type: bool + description: Enable or disable reception of additional-paths. + send: + type: str + description: 'Select an option to send multiple paths for same prefix through + bgp updates. + + any: Send any eligible path. + + backup: Best path and installed backup path. + + ecmp: All paths in best path ECMP group. + + limit: Limit to n eligible paths. + + disabled: Disable sending any paths.' + valid_values: + - any + - backup + - ecmp + - limit + - disabled + send_limit: + type: int + description: Number of paths to send through bgp updates. For this setting, + `send` must be set to `limit` or `ecmp`. + convert_types: + - str + min: 2 + max: 64 + flow_tracking: + type: dict + keys: + trackers: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: Tracker Name. + record_export: + type: dict + keys: + on_inactive_timeout: + type: int + convert_types: + - str + min: 3000 + max: 900000 + description: Flow record inactive export timeout in milliseconds. + on_interval: + type: int + convert_types: + - str + min: 1000 + max: 36000000 + description: Flow record export interval in milliseconds. + exporters: + type: list + primary_key: name + items: + type: dict + keys: + name: + type: str + description: Exporter Name. + collector: + type: dict + keys: + host: + type: str + description: Collector IPv4 address or IPv6 address or fully + qualified domain name. + port: + type: int + description: Collector Port Number. + min: 1 + max: 65535 + convert_types: + - str + format: + type: dict + keys: + ipfix_version: + type: int + convert_types: + - str + local_interface: + type: str + description: Local Source Interface. + template_interval: + type: int + convert_types: + - str + min: 5000 + max: 3600000 + description: Template interval in milliseconds. + shutdown: + type: bool + default: false interface_ip_nat: type: dict keys: @@ -12837,9 +20507,9 @@ $defs: pool_name: type: str description: 'required if ''nat_type'' is pool, pool-address-only - or pool-full-cone + or pool-full-cone. - ignored if ''nat_type'' is overload + ignored if ''nat_type'' is overload. ' priority: @@ -12853,13 +20523,12 @@ $defs: $ref: eos_cli_config_gen#/$defs/interface_ip_nat_static interface_ip_nat_static: type: list - primary_key: original_ip items: type: dict keys: access_list: type: str - description: '''access_list'' and ''group'' are mutual exclusive' + description: '''access_list'' and ''group'' are mutual exclusive.' comment: type: str direction: @@ -12880,12 +20549,15 @@ $defs: - str min: 1 max: 65535 - description: '''access_list'' and ''group'' are mutual exclusive' + description: '''access_list'' and ''group'' are mutual exclusive.' original_ip: type: str - description: IPv4 address + description: IPv4 address. The combination of `original_ip` and `original_port` + must be unique. original_port: type: int + description: TCP/UDP port. The combination of `original_ip` and `original_port` + must be unique. convert_types: - str min: 1 @@ -12904,11 +20576,11 @@ $defs: translated_ip: type: str required: true - description: IPv4 address + description: IPv4 address. translated_port: type: int convert_types: - str min: 1 max: 65535 - description: requires 'original_port' + description: requires 'original_port'. diff --git a/python-avd/tests/schema_tools/artifacts/ethernet-interfaces.json b/python-avd/tests/schema_tools/artifacts/ethernet-interfaces.json new file mode 100644 index 00000000000..50788ca9c6e --- /dev/null +++ b/python-avd/tests/schema_tools/artifacts/ethernet-interfaces.json @@ -0,0 +1,2460 @@ +{ + "root_dir": "/home/holbech/avd/python-avd/scripts", + "is_for_test": true, + "management_interfaces": [ + { + "name": "Management1", + "description": "OOB_MANAGEMENT", + "vrf": "MGMT", + "ip_address": "10.73.255.122/24", + "gateway": "10.73.255.2" + } + ], + "inventory_file": "/home/holbech/avd/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/hosts.ini", + "inventory_dir": "/home/holbech/avd/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory", + "inventory_hostname": "ethernet-interfaces", + "inventory_hostname_short": "ethernet-interfaces", + "group_names": [ + "test_hosts" + ], + "ethernet_interfaces": [ + { + "name": "Ethernet1", + "peer": "DC1-SPINE1", + "peer_interface": "Ethernet1", + "peer_type": "spine", + "description": "P2P_LINK_TO_DC1-SPINE1_Ethernet1", + "speed": "forced 100gfull", + "mtu": 1500, + "l2_mtu": 8000, + "l2_mru": 8000, + "ip_address": "172.31.255.1/31", + "link_tracking_groups": [ + { + "name": "EVPN_MH_ES1", + "direction": "upstream" + } + ], + "priority_flow_control": { + "enabled": true, + "priorities": [ + { + "priority": 5, + "no_drop": false + } + ] + }, + "bfd": { + "echo": true, + "interval": 500, + "min_rx": 500, + "multiplier": 5 + }, + "bgp": { + "session_tracker": "ST1" + }, + "ip_verify_unicast_source_reachable_via": "rx", + "tcp_mss_ceiling": { + "ipv4_segment_size": 70, + "ipv6_segment_size": 75, + "direction": "egress" + }, + "switchport": { + "enabled": false, + "port_security": { + "enabled": true, + "mac_address_maximum": { + "disabled": true + } + }, + "trunk": { + "allowed_vlan": "110-111,210-211", + "native_vlan": 5, + "native_vlan_tag": true, + "groups": [ + "g1", + "g2" + ], + "private_vlan_secondary": true + }, + "access_vlan": 200, + "phone": { + "vlan": 110, + "trunk": "tagged" + }, + "mode": "dot1q-tunnel", + "pvlan_mapping": "20-30", + "dot1q": { + "ethertype": 1536, + "vlan_tag": "required" + }, + "vlan_translations": { + "in_required": true, + "direction_in": [ + { + "from": 10, + "to": 24 + }, + { + "from": 37, + "to": 49, + "inner_vlan_from": 56 + }, + { + "from": 23, + "to": 45, + "dot1q_tunnel": true + } + ], + "direction_both": [ + { + "from": 24, + "inner_vlan_from": 78, + "network": true, + "to": 46 + }, + { + "from": 12, + "to": 20 + }, + { + "from": 43, + "to": 30, + "dot1q_tunnel": true + }, + { + "from": 24, + "inner_vlan_from": 78, + "network": false, + "to": 46 + } + ], + "direction_out": [ + { + "from": 34, + "to": 50 + }, + { + "from": 10, + "to": 45, + "inner_vlan_to": 34 + }, + { + "from": 45, + "dot1q_tunnel_to": "all" + }, + { + "from": 55 + } + ] + }, + "vlan_forwarding_accept_all": true, + "source_interface": "tx", + "backup_link": { + "interface": "Ethernet5", + "prefer_vlan": 10 + }, + "backup": { + "dest_macaddr": "01:00:00:00:00:00", + "mac_move_burst": 20, + "mac_move_burst_interval": 30, + "initial_mac_move_delay": 10, + "preemption_delay": 35 + } + }, + "eos_cli": "comment\nComment created from eos_cli under ethernet_interfaces.Ethernet1\nEOF\n", + "ip_igmp_host_proxy": { + "enabled": true, + "groups": [ + { + "group": "239.0.0.1" + }, + { + "group": "239.0.0.2", + "exclude": [ + { + "source": "10.0.2.1" + } + ] + }, + { + "group": "239.0.0.3", + "include": [ + { + "source": "10.0.3.1" + } + ] + }, + { + "group": "239.0.0.4", + "exclude": [ + { + "source": "10.0.4.1" + }, + { + "source": "10.0.4.2" + } + ], + "include": [ + { + "source": "10.0.4.3" + }, + { + "source": "10.0.4.4" + } + ] + } + ], + "report_interval": 2, + "access_lists": [ + { + "name": "ACL1" + }, + { + "name": "ACL2" + } + ], + "version": 2 + } + }, + { + "name": "Ethernet2", + "peer": "SRV-POD03", + "peer_interface": "Eth1", + "peer_type": "server", + "description": "SRV-POD02_Eth1", + "tcp_mss_ceiling": { + "ipv4_segment_size": 70, + "direction": "ingress" + }, + "multicast": { + "ipv4": { + "static": true, + "boundaries": [ + { + "boundary": "ACL_MULTICAST" + } + ] + }, + "ipv6": { + "boundaries": [ + { + "boundary": "ACL_V6_MULTICAST" + } + ] + } + }, + "storm_control": { + "all": { + "level": 10 + }, + "broadcast": { + "level": 500, + "unit": "pps" + }, + "unknown_unicast": { + "level": 1, + "unit": "percent" + } + }, + "priority_flow_control": { + "enabled": true, + "priorities": [ + { + "priority": 5, + "no_drop": true + } + ] + }, + "spanning_tree_bpduguard": "disabled", + "spanning_tree_bpdufilter": "disabled", + "switchport": { + "mode": "trunk", + "trunk": { + "allowed_vlan": "110-111,210-211", + "private_vlan_secondary": false + }, + "enabled": true, + "dot1q": { + "vlan_tag": "disallowed" + }, + "port_security": { + "mac_address_maximum": { + "limit": 100 + }, + "violation": { + "mode": "protect", + "protect_log": true + } + }, + "vlan_translations": { + "in_required": false + }, + "backup_link": { + "prefer_vlan": 20 + } + } + }, + { + "name": "Ethernet3", + "peer": "DC1-SPINE2", + "peer_interface": "Ethernet2", + "peer_type": "spine", + "description": "P2P_LINK_TO_DC1-SPINE2_Ethernet2", + "mtu": 1500, + "ip_address": "172.31.128.1/31", + "snmp_trap_link_change": false, + "link_tracking_groups": [ + { + "name": "EVPN_MH_ES2", + "direction": "downstream" + } + ], + "ipv6_enable": true, + "ipv6_address": "2002:ABDC::1/64", + "ipv6_nd_prefixes": [ + { + "ipv6_prefix": "2345:ABCD:3FE0::1/96", + "valid_lifetime": "infinite", + "preferred_lifetime": 50, + "no_autoconfig_flag": true + }, + { + "ipv6_prefix": "2345:ABCD:3FE0::2/96", + "valid_lifetime": 50, + "preferred_lifetime": "infinite", + "no_autoconfig_flag": false + }, + { + "ipv6_prefix": "2345:ABCD:3FE0::3/96", + "valid_lifetime": 100000, + "no_autoconfig_flag": true + } + ], + "priority_flow_control": { + "enabled": false + }, + "spanning_tree_guard": "root", + "tcp_mss_ceiling": { + "ipv6_segment_size": 65 + }, + "switchport": { + "enabled": false, + "mode": "trunk", + "trunk": { + "native_vlan": 5 + }, + "port_security": { + "mac_address_maximum": { + "disabled": false + }, + "violation": { + "mode": "shutdown" + }, + "vlan_default_mac_address_maximum": 2, + "vlans": [ + { + "range": "1-3", + "mac_address_maximum": 3 + } + ] + }, + "vlan_translations": { + "out_required": false, + "direction_out": [ + { + "from": 23, + "dot1q_tunnel_to": 50 + } + ] + }, + "backup_link": { + "interface": "Ethernet4" + } + } + }, + { + "name": "Ethernet4", + "description": "Molecule IPv6", + "shutdown": true, + "mtu": 9100, + "ipv6_enable": true, + "ipv6_address": "2020::2020/64", + "ipv6_address_link_local": "FE80:FEA::AB65/64", + "ipv6_nd_ra_disabled": true, + "ipv6_nd_managed_config_flag": true, + "ipv6_access_group_in": "IPv6_ACL_IN", + "ipv6_access_group_out": "IPv6_ACL_OUT", + "snmp_trap_link_change": true, + "priority_flow_control": { + "enabled": true + }, + "spanning_tree_guard": "disabled", + "tcp_mss_ceiling": { + "ipv4_segment_size": 65 + }, + "multicast": { + "ipv4": { + "static": true, + "boundaries": [ + { + "boundary": "224.0.1.0/24", + "out": true + }, + { + "boundary": "224.0.2.0/24" + } + ] + }, + "ipv6": { + "boundaries": [ + { + "boundary": "ff00::/16" + }, + { + "boundary": "ff01::/16" + } + ] + } + }, + "switchport": { + "enabled": false, + "port_security": { + "violation": { + "mode": "protect" + } + } + } + }, + { + "name": "Ethernet5", + "description": "Molecule Routing", + "shutdown": false, + "mtu": 9100, + "ospf_network_point_to_point": true, + "ospf_area": 100, + "ospf_cost": 99, + "ospf_authentication": "message-digest", + "ospf_authentication_key": "asfddja23452", + "ospf_message_digest_keys": [ + { + "id": 1, + "hash_algorithm": "sha512", + "key": "asfddja23452" + } + ], + "pim": { + "ipv4": { + "dr_priority": 200, + "sparse_mode": true, + "border_router": true, + "bfd": true, + "bidirectional": true, + "hello": { + "count": 2.5, + "interval": 10 + } + } + }, + "isis_enable": "ISIS_TEST", + "isis_bfd": true, + "isis_passive": false, + "isis_metric": 99, + "isis_network_point_to_point": true, + "isis_circuit_type": "level-2", + "isis_hello_padding": false, + "isis_authentication_mode": "md5", + "isis_authentication_key": "asfddja23452", + "spanning_tree_guard": "loop", + "switchport": { + "enabled": false, + "access_vlan": 220 + } + }, + { + "name": "Ethernet6", + "logging": { + "event": { + "link_status": true, + "congestion_drops": true, + "spanning_tree": true, + "storm_control_discards": true + } + }, + "peer": "SRV-POD02", + "peer_interface": "Eth1", + "peer_type": "server", + "description": "SRV-POD02_Eth1", + "switchport": { + "enabled": true, + "trunk": { + "allowed_vlan": "110-111,210-211" + }, + "mode": "trunk" + }, + "spanning_tree_bpduguard": "enabled", + "spanning_tree_bpdufilter": "enabled" + }, + { + "name": "Ethernet7", + "description": "Molecule L2", + "shutdown": false, + "switchport": { + "enabled": true + }, + "mtu": 7000, + "ptp": { + "enable": true, + "announce": { + "interval": 10, + "timeout": 30 + }, + "delay_req": 20, + "delay_mechanism": "p2p", + "sync_message": { + "interval": 5 + }, + "role": "master", + "vlan": "all", + "transport": "layer2" + }, + "service_profile": "QoS", + "qos": { + "trust": "cos", + "cos": 5 + }, + "spanning_tree_bpdufilter": true, + "spanning_tree_bpduguard": true, + "spanning_tree_portfast": "edge", + "vmtracer": true, + "storm_control": { + "all": { + "level": 75, + "unit": "percent" + }, + "broadcast": { + "level": 10, + "unit": "pps" + }, + "multicast": { + "level": 50, + "unit": null + }, + "unknown_unicast": { + "level": 10, + "unit": "percent" + } + }, + "transceiver": { + "media": { + "override": "100gbase-ar4" + } + } + }, + { + "name": "Ethernet8", + "description": "to WAN-ISP1-01 Ethernet2", + "switchport": { + "enabled": false + }, + "lldp": { + "transmit": false, + "receive": false + } + }, + { + "name": "Ethernet8.101", + "description": "to WAN-ISP-01 Ethernet2.101 - VRF-C1", + "encapsulation_dot1q": { + "vlan": 101 + }, + "ip_address": "172.31.128.1/31", + "ipv6_enable": true, + "ipv6_address": "2002:ABDC::1/64" + }, + { + "name": "Ethernet9", + "description": "interface_with_mpls_enabled", + "switchport": { + "enabled": false + }, + "ip_address": "172.31.128.9/31", + "multicast": { + "ipv4": { + "boundaries": [ + { + "boundary": "ACL_MULTICAST", + "out": true + } + ] + }, + "ipv6": { + "static": true + } + }, + "mpls": { + "ip": true, + "ldp": { + "interface": true + } + } + }, + { + "name": "Ethernet10", + "description": "interface_with_mpls_disabled", + "switchport": { + "enabled": false + }, + "ip_address": "172.31.128.10/31", + "mpls": { + "ip": false, + "ldp": { + "interface": false + } + } + }, + { + "name": "Ethernet11", + "description": "interface_in_mode_access_accepting_tagged_LACP", + "switchport": { + "enabled": true, + "mode": "access", + "access_vlan": 200 + }, + "l2_protocol": { + "encapsulation_dot1q_vlan": 200 + }, + "spanning_tree_bpduguard": false, + "spanning_tree_bpdufilter": false + }, + { + "name": "Ethernet12", + "description": "interface_with_dot1q_tunnel", + "switchport": { + "enabled": true, + "mode": "dot1q-tunnel", + "access_vlan": 300 + } + }, + { + "name": "Ethernet13", + "logging": { + "event": { + "link_status": false, + "congestion_drops": false, + "spanning_tree": false, + "storm_control_discards": false + } + }, + "description": "interface_in_mode_access_with_voice", + "switchport": { + "enabled": true, + "trunk": { + "native_vlan": 100 + }, + "mode": "trunk phone", + "phone": { + "trunk": "untagged", + "vlan": 70 + } + } + }, + { + "name": "Ethernet14", + "logging": { + "event": { + "link_status": true + } + }, + "peer": "SRV-POD02", + "peer_interface": "Eth1", + "peer_type": "server", + "description": "SRV-POD02_Eth1", + "switchport": { + "enabled": true, + "mode": "trunk", + "trunk": { + "allowed_vlan": "110-111,210-211" + } + } + }, + { + "name": "Ethernet15", + "description": "PVLAN Promiscuous Access - only one secondary", + "switchport": { + "enabled": true, + "mode": "access", + "access_vlan": 110, + "pvlan_mapping": 111 + } + }, + { + "name": "Ethernet16", + "description": "PVLAN Promiscuous Trunk - vlan translation out", + "switchport": { + "enabled": true, + "mode": "trunk", + "trunk": { + "allowed_vlan": "110-112" + }, + "vlan_translations": { + "out_required": true, + "direction_out": [ + { + "from": "111-112", + "to": 110 + } + ] + } + } + }, + { + "name": "Ethernet17", + "description": "PVLAN Secondary Trunk", + "switchport": { + "enabled": true, + "mode": "trunk", + "trunk": { + "allowed_vlan": "110-112", + "private_vlan_secondary": true + } + } + }, + { + "name": "Ethernet18", + "description": "PBR Description", + "mtu": 1500, + "switchport": { + "enabled": false + }, + "ip_address": "192.0.2.1/31", + "service_policy": { + "pbr": { + "input": "MyLANServicePolicy" + } + } + }, + { + "name": "Ethernet19", + "description": "Switched port with no LLDP rx/tx", + "switchport": { + "enabled": true, + "mode": "access", + "access_vlan": 110 + }, + "lldp": { + "transmit": false, + "receive": false, + "ztp_vlan": 666 + } + }, + { + "name": "Ethernet20", + "description": "Port patched through patch-panel to pseudowire", + "switchport": { + "enabled": false + }, + "lldp": { + "transmit": false, + "receive": false + } + }, + { + "name": "Ethernet21", + "switchport": { + "enabled": true + }, + "description": "200MBit/s shape", + "qos": { + "trust": "disabled" + }, + "shape": { + "rate": "200000 kbps" + } + }, + { + "name": "Ethernet22", + "switchport": { + "enabled": true + }, + "description": "10% shape", + "shape": { + "rate": "10 percent" + } + }, + { + "name": "Ethernet23", + "switchport": { + "enabled": true + }, + "description": "Error-correction encoding", + "error_correction_encoding": { + "fire_code": true, + "reed_solomon": true + } + }, + { + "name": "Ethernet24", + "switchport": { + "enabled": true + }, + "description": "Disable error-correction encoding", + "error_correction_encoding": { + "enabled": false + } + }, + { + "name": "Ethernet25", + "switchport": { + "enabled": true + }, + "description": "Molecule MAC", + "mac_access_group_in": "MAC_ACL_IN", + "mac_access_group_out": "MAC_ACL_OUT" + }, + { + "name": "Ethernet26", + "switchport": { + "enabled": false + } + }, + { + "name": "Ethernet26.1", + "description": "TENANT_A pseudowire 1 interface", + "encapsulation_vlan": { + "client": { + "encapsulation": "unmatched" + } + } + }, + { + "name": "Ethernet26.100", + "description": "TENANT_A pseudowire 1 interface", + "vlan_id": 10, + "encapsulation_vlan": { + "client": { + "encapsulation": "dot1q", + "vlan": 100 + }, + "network": { + "encapsulation": "client" + } + } + }, + { + "name": "Ethernet26.200", + "description": "TENANT_A pseudowire 2 interface", + "encapsulation_vlan": { + "client": { + "encapsulation": "dot1q", + "vlan": 200 + } + } + }, + { + "name": "Ethernet26.300", + "description": "TENANT_A pseudowire 3 interface", + "encapsulation_vlan": { + "client": { + "encapsulation": "dot1q", + "vlan": 300 + }, + "network": { + "encapsulation": "dot1q", + "vlan": 400 + } + } + }, + { + "name": "Ethernet26.400", + "description": "TENANT_A pseudowire 3 interface", + "encapsulation_vlan": { + "client": { + "encapsulation": "dot1q", + "outer_vlan": 400, + "inner_vlan": 20 + }, + "network": { + "encapsulation": "dot1q", + "outer_vlan": 401, + "inner_vlan": 21 + } + } + }, + { + "name": "Ethernet26.500", + "description": "TENANT_A pseudowire 3 interface", + "encapsulation_vlan": { + "client": { + "encapsulation": "dot1q", + "outer_vlan": 500, + "inner_vlan": 50 + }, + "network": { + "encapsulation": "client" + } + } + }, + { + "name": "Ethernet27", + "switchport": { + "enabled": true + }, + "description": "EVPN-Vxlan single-active redundancy", + "evpn_ethernet_segment": { + "identifier": "0000:0000:0000:0102:0304", + "route_target": "00:00:01:02:03:04", + "redundancy": "single-active", + "designated_forwarder_election": { + "algorithm": "preference", + "preference_value": 100, + "dont_preempt": true, + "hold_time": 10, + "candidate_reachability_required": true + } + } + }, + { + "name": "Ethernet28", + "switchport": { + "enabled": true + }, + "description": "EVPN-MPLS multihoming", + "evpn_ethernet_segment": { + "identifier": "0000:0000:0000:0102:0305", + "route_target": "00:00:01:02:03:05", + "mpls": { + "shared_index": 100, + "tunnel_flood_filter_time": 100 + } + } + }, + { + "name": "Ethernet29", + "switchport": { + "enabled": true + }, + "description": "DOT1X Testing - auto phone true", + "dot1x": { + "port_control": "auto", + "port_control_force_authorized_phone": true + } + }, + { + "name": "Ethernet30", + "switchport": { + "enabled": true + }, + "description": "DOT1X Testing - force-authorized phone false", + "dot1x": { + "port_control": "force-authorized", + "port_control_force_authorized_phone": false + } + }, + { + "name": "Ethernet31", + "switchport": { + "enabled": true + }, + "description": "DOT1X Testing - force-unauthorized - no phone", + "dot1x": { + "port_control": "force-unauthorized" + } + }, + { + "name": "Ethernet32", + "switchport": { + "enabled": true + }, + "description": "DOT1X Testing - auto reauthentication", + "dot1x": { + "port_control": "auto", + "reauthentication": true + } + }, + { + "name": "Ethernet33", + "switchport": { + "enabled": true + }, + "description": "DOT1X Testing - pae mode authenticator", + "dot1x": { + "pae": { + "mode": "authenticator" + } + } + }, + { + "name": "Ethernet34", + "switchport": { + "enabled": true + }, + "description": "DOT1X Testing - authentication_failure allow", + "dot1x": { + "authentication_failure": { + "action": "allow", + "allow_vlan": 800 + } + } + }, + { + "name": "Ethernet35", + "switchport": { + "enabled": true + }, + "description": "DOT1X Testing - authentication_failure drop", + "dot1x": { + "authentication_failure": { + "action": "drop" + } + } + }, + { + "name": "Ethernet36", + "switchport": { + "enabled": true + }, + "description": "DOT1X Testing - host-mode single-host", + "dot1x": { + "host_mode": { + "mode": "single-host" + } + } + }, + { + "name": "Ethernet37", + "switchport": { + "enabled": true + }, + "description": "DOT1X Testing - host-mode multi-host", + "dot1x": { + "host_mode": { + "mode": "multi-host" + } + } + }, + { + "name": "Ethernet38", + "switchport": { + "enabled": true + }, + "description": "DOT1X Testing - host-mode multi-host authenticated", + "dot1x": { + "host_mode": { + "mode": "multi-host", + "multi_host_authenticated": true + } + } + }, + { + "name": "Ethernet39", + "switchport": { + "enabled": true + }, + "description": "DOT1X Testing - mac_based_authentication host-mode common true", + "dot1x": { + "mac_based_authentication": { + "enabled": true, + "host_mode_common": true + } + } + }, + { + "name": "Ethernet40", + "switchport": { + "enabled": true + }, + "description": "DOT1X Testing - mac_based_authentication always", + "dot1x": { + "mac_based_authentication": { + "enabled": true, + "always": true + } + } + }, + { + "name": "Ethernet41", + "switchport": { + "enabled": true + }, + "description": "DOT1X Testing - mac_based_authentication always and host-mode common", + "dot1x": { + "mac_based_authentication": { + "enabled": true, + "always": true, + "host_mode_common": true + } + } + }, + { + "name": "Ethernet42", + "switchport": { + "enabled": true + }, + "description": "DOT1X Testing - mac_based_authentication", + "dot1x": { + "mac_based_authentication": { + "enabled": true + } + } + }, + { + "name": "Ethernet43", + "switchport": { + "enabled": true + }, + "description": "DOT1X Testing - timeout values", + "dot1x": { + "timeout": { + "idle_host": 15, + "quiet_period": 10, + "reauth_period": "server", + "reauth_timeout_ignore": true, + "tx_period": 6 + } + } + }, + { + "name": "Ethernet44", + "switchport": { + "enabled": true + }, + "description": "DOT1X Testing - reauthorization_request_limit", + "dot1x": { + "reauthorization_request_limit": 3, + "eapol": { + "disabled": true + } + } + }, + { + "name": "Ethernet45", + "switchport": { + "enabled": true + }, + "description": "DOT1X Testing - all features", + "dot1x": { + "port_control": "auto", + "reauthentication": true, + "pae": { + "mode": "authenticator" + }, + "authentication_failure": { + "action": "allow", + "allow_vlan": 800 + }, + "host_mode": { + "mode": "multi-host", + "multi_host_authenticated": true + }, + "mac_based_authentication": { + "enabled": true + }, + "timeout": { + "idle_host": 10, + "quiet_period": 10, + "reauth_period": "server", + "reauth_timeout_ignore": true, + "tx_period": 10 + }, + "eapol": { + "disabled": false, + "authentication_failure_fallback_mba": { + "enabled": true, + "timeout": 600 + } + }, + "reauthorization_request_limit": 2, + "unauthorized": { + "access_vlan_membership_egress": true, + "native_vlan_membership_egress": true + } + } + }, + { + "name": "Ethernet46", + "description": "native-vlan-tag-precedence", + "switchport": { + "enabled": true, + "mode": "trunk", + "trunk": { + "native_vlan_tag": true, + "native_vlan": 100 + } + } + }, + { + "name": "Ethernet47", + "description": "IP Helper", + "switchport": { + "enabled": false + }, + "ip_address": "172.31.255.1/31", + "ip_helpers": [ + { + "ip_helper": "10.10.96.101", + "source_interface": "Loopback0" + }, + { + "ip_helper": "10.10.96.151", + "vrf": "MGMT" + }, + { + "ip_helper": "10.10.96.150", + "source_interface": "Loopback0", + "vrf": "MGMT" + }, + { + "ip_helper": "10.10.64.151" + } + ] + }, + { + "name": "Ethernet48", + "description": "Load Interval", + "switchport": { + "enabled": true + }, + "load_interval": 5 + }, + { + "name": "Ethernet50", + "switchport": { + "enabled": true + }, + "description": "SFlow Interface Testing - SFlow ingress enabled", + "sflow": { + "enable": true + } + }, + { + "name": "Ethernet51", + "switchport": { + "enabled": true + }, + "description": "SFlow Interface Testing - SFlow egress enabled", + "sflow": { + "egress": { + "enable": true + } + } + }, + { + "name": "Ethernet52", + "switchport": { + "enabled": true + }, + "description": "SFlow Interface Testing - SFlow ingress and egress unmodified enabled", + "sflow": { + "enable": true, + "egress": { + "unmodified_enable": true + } + } + }, + { + "name": "Ethernet53", + "switchport": { + "enabled": true + }, + "description": "SFlow Interface Testing - SFlow ingress and egress disabled", + "sflow": { + "enable": false, + "egress": { + "enable": false + } + } + }, + { + "name": "Ethernet54", + "switchport": { + "enabled": true + }, + "description": "SFlow Interface Testing - SFlow ingress and egress unmodified disabled", + "sflow": { + "enable": false, + "egress": { + "unmodified_enable": false + } + } + }, + { + "name": "Ethernet55", + "description": "DHCPv6 Relay Testing", + "switchport": { + "enabled": false + }, + "shutdown": false, + "ipv6_address": "a0::1/64", + "ipv6_dhcp_relay_destinations": [ + { + "address": "a0::2", + "link_address": "a0::3" + }, + { + "address": "a0::4", + "link_address": "a0::5", + "vrf": "TEST", + "local_interface": "Loopback55" + } + ] + }, + { + "name": "Ethernet56", + "switchport": { + "enabled": true + }, + "description": "Interface with poe commands and limit in class", + "poe": { + "priority": "low", + "reboot": { + "action": "power-off" + }, + "link_down": { + "action": "power-off", + "power_off_delay": 10 + }, + "shutdown": { + "action": "maintain" + }, + "limit": { + "class": 4, + "fixed": false + }, + "negotiation_lldp": false + } + }, + { + "name": "Ethernet57", + "switchport": { + "enabled": true + }, + "description": "Interface with poe commands and limit in watts", + "poe": { + "disabled": false, + "priority": "critical", + "reboot": { + "action": "maintain" + }, + "link_down": { + "action": "maintain" + }, + "shutdown": { + "action": "power-off" + }, + "limit": { + "watts": 45, + "fixed": true + }, + "legacy_detect": true, + "negotiation_lldp": true + } + }, + { + "name": "Ethernet58", + "switchport": { + "enabled": true + }, + "description": "Interface with poe disabled and no other poe keys", + "poe": { + "disabled": true + } + }, + { + "name": "Ethernet60", + "switchport": { + "enabled": true + }, + "description": "IP NAT Testing", + "ip_nat": { + "destination": { + "dynamic": [ + { + "access_list": "ACL1", + "pool_name": "POOL1" + }, + { + "access_list": "ACL2", + "pool_name": "POOL1", + "comment": "POOL1 shared with ACL1/2" + }, + { + "access_list": "ACL3", + "pool_name": "POOL3", + "priority": 10 + }, + { + "access_list": "ACL4", + "pool_name": "POOL4", + "comment": "Priority low end", + "priority": 1 + }, + { + "access_list": "ACL6", + "pool_name": "POOL6", + "comment": "Priority default", + "priority": 0 + }, + { + "access_list": "ACL5", + "pool_name": "POOL5", + "comment": "Priority high end", + "priority": 4294967295 + } + ], + "static": [ + { + "original_ip": "1.0.0.1", + "translated_ip": "2.0.0.1" + }, + { + "original_ip": "1.0.0.2", + "translated_ip": "2.0.0.2", + "original_port": 22 + }, + { + "original_ip": "1.0.0.3", + "translated_ip": "2.0.0.3", + "original_port": 22, + "translated_port": 23 + }, + { + "original_ip": "1.0.0.4", + "translated_ip": "2.0.0.4", + "original_port": 22, + "translated_port": 23, + "protocol": "udp" + }, + { + "original_ip": "1.0.0.5", + "translated_ip": "2.0.0.5", + "original_port": 22, + "translated_port": 23, + "protocol": "tcp", + "group": 1 + }, + { + "original_ip": "1.0.0.6", + "translated_ip": "2.0.0.6", + "original_port": 22, + "translated_port": 23, + "protocol": "tcp", + "group": 2, + "priority": 5, + "comment": "Comment Test" + }, + { + "original_ip": "1.0.0.7", + "translated_ip": "2.0.0.7", + "access_list": "ACL21" + }, + { + "original_ip": "239.0.0.1", + "translated_ip": "239.0.0.2", + "direction": "egress" + } + ] + }, + "source": { + "dynamic": [ + { + "access_list": "ACL11", + "pool_name": "POOL11", + "nat_type": "pool" + }, + { + "access_list": "ACL12", + "pool_name": "POOL11", + "comment": "POOL11 shared with ACL11/12", + "nat_type": "pool" + }, + { + "access_list": "ACL13", + "pool_name": "POOL13", + "priority": 10, + "nat_type": "pool" + }, + { + "access_list": "ACL14", + "pool_name": "POOL14", + "comment": "Priority low end", + "priority": 1, + "nat_type": "pool" + }, + { + "access_list": "ACL16", + "pool_name": "POOL16", + "comment": "Priority default", + "priority": 0, + "nat_type": "pool" + }, + { + "access_list": "ACL15", + "pool_name": "POOL15", + "comment": "Priority high end", + "priority": 4294967295, + "nat_type": "pool" + }, + { + "access_list": "ACL17", + "comment": "Priority_10", + "priority": 10, + "nat_type": "overload" + }, + { + "access_list": "ACL18", + "pool_name": "POOL18", + "comment": "Priority_10", + "priority": 10, + "nat_type": "pool-address-only" + }, + { + "access_list": "ACL19", + "pool_name": "POOL19", + "comment": "Priority_10", + "priority": 10, + "nat_type": "pool-full-cone" + } + ], + "static": [ + { + "original_ip": "3.0.0.1", + "translated_ip": "4.0.0.1" + }, + { + "original_ip": "3.0.0.2", + "translated_ip": "4.0.0.2", + "original_port": 22 + }, + { + "original_ip": "3.0.0.3", + "translated_ip": "4.0.0.3", + "original_port": 22, + "translated_port": 23 + }, + { + "original_ip": "3.0.0.4", + "translated_ip": "4.0.0.4", + "original_port": 22, + "translated_port": 23, + "protocol": "udp" + }, + { + "original_ip": "3.0.0.5", + "translated_ip": "4.0.0.5", + "original_port": 22, + "translated_port": 23, + "protocol": "tcp", + "group": 1 + }, + { + "original_ip": "3.0.0.6", + "translated_ip": "4.0.0.6", + "original_port": 22, + "translated_port": 23, + "protocol": "tcp", + "group": 2, + "priority": 5, + "comment": "Comment Test" + }, + { + "original_ip": "3.0.0.7", + "translated_ip": "4.0.0.7", + "access_list": "ACL21" + }, + { + "original_ip": "3.0.0.8", + "translated_ip": "4.0.0.8", + "direction": "ingress" + } + ] + } + } + }, + { + "name": "Ethernet61", + "logging": { + "event": { + "link_status": false, + "congestion_drops": false, + "spanning_tree": false, + "storm_control_discards": false + } + }, + "description": "interface_in_mode_access_with_voice", + "switchport": { + "enabled": true, + "trunk": { + "native_vlan": 100 + }, + "mode": "trunk phone", + "phone": { + "trunk": "untagged phone", + "vlan": 70 + } + } + }, + { + "name": "Ethernet62", + "logging": { + "event": { + "link_status": false, + "congestion_drops": false, + "spanning_tree": false, + "storm_control_discards": false + } + }, + "description": "interface_in_mode_access_with_voice", + "switchport": { + "enabled": true, + "trunk": { + "native_vlan": 100 + }, + "mode": "trunk phone", + "phone": { + "trunk": "tagged phone", + "vlan": 70 + } + } + }, + { + "name": "Ethernet63", + "description": "DHCP client interface", + "switchport": { + "enabled": false + }, + "ip_address": "dhcp", + "dhcp_client_accept_default_route": true + }, + { + "name": "Ethernet64", + "description": "DHCP server interface", + "switchport": { + "enabled": false + }, + "ip_address": "192.168.42.42/24", + "dhcp_server_ipv4": true, + "dhcp_server_ipv6": true + }, + { + "name": "Ethernet69", + "switchport": { + "enabled": true + }, + "description": "IP NAT service-profile", + "ip_nat": { + "service_profile": "TEST-NAT-PROFILE" + } + }, + { + "name": "Ethernet65", + "description": "Multiple VRIDs", + "switchport": { + "enabled": false + }, + "shutdown": false, + "ip_address": "192.0.2.2/25", + "ipv6_enable": true, + "ipv6_address": "2001:db8::2/64", + "ipv6_address_link_local": "fe80::2/64", + "vrrp_ids": [ + { + "id": 1, + "priority_level": 105, + "advertisement": { + "interval": 2 + }, + "preempt": { + "enabled": true, + "delay": { + "minimum": 30, + "reload": 800 + } + }, + "ipv4": { + "address": "192.0.2.1" + } + }, + { + "id": 2, + "preempt": { + "enabled": true, + "delay": null + }, + "ipv6": { + "address": "2001:db8::1" + } + } + ] + }, + { + "name": "Ethernet66", + "description": "Multiple VRIDs and tracking", + "shutdown": false, + "switchport": { + "enabled": false + }, + "ip_address": "192.0.2.2/25", + "ipv6_enable": true, + "ipv6_address": "2001:db8::2/64", + "ipv6_address_link_local": "fe80::2/64", + "vrrp_ids": [ + { + "id": 1, + "priority_level": 105, + "advertisement": { + "interval": 2 + }, + "preempt": { + "enabled": true, + "delay": { + "minimum": 30, + "reload": 800 + } + }, + "ipv4": { + "address": "192.0.2.1" + }, + "tracked_object": [ + { + "name": "ID1-TrackedObjectDecrement", + "decrement": 5 + }, + { + "name": "ID1-TrackedObjectShutdown", + "shutdown": true + } + ] + }, + { + "id": 2, + "preempt": { + "enabled": true, + "delay": null + }, + "ipv6": { + "address": "2001:db8::1" + }, + "tracked_object": [ + { + "name": "ID2-TrackedObjectDecrement", + "decrement": 10 + }, + { + "name": "ID2-TrackedObjectShutdown", + "shutdown": true + } + ] + }, + { + "id": 3, + "timers": { + "delay": { + "reload": 900 + } + }, + "preempt": { + "enabled": false + }, + "ipv4": { + "address": "100.64.0.1", + "version": 3 + } + } + ] + }, + { + "name": "Ethernet67", + "switchport": { + "enabled": true + }, + "description": "Custom_Transceiver_Frequency", + "shutdown": false, + "transceiver": { + "frequency": 190050 + } + }, + { + "name": "Ethernet67.1", + "description": "Test_encapsulation_dot1q", + "encapsulation_dot1q": { + "vlan": 4, + "inner_vlan": 34 + } + }, + { + "name": "Ethernet68", + "switchport": { + "enabled": true + }, + "description": "Custom_Transceiver_Frequency", + "shutdown": false, + "transceiver": { + "frequency": 190080, + "frequency_unit": "ghz", + "media": { + "override": "100gbase-ar4" + } + } + }, + { + "name": "Ethernet68.1", + "description": "Test_encapsulation_vlan1", + "encapsulation_vlan": { + "client": { + "outer_vlan": 23, + "inner_vlan": 45, + "encapsulation": "dot1q", + "inner_encapsulation": "dot1q" + }, + "network": { + "encapsulation": "dot1ad", + "outer_vlan": 32, + "inner_vlan": 54, + "inner_encapsulation": "dot1ad" + } + } + }, + { + "name": "Ethernet68.2", + "description": "Test_encapsulation_vlan2", + "encapsulation_vlan": { + "client": { + "encapsulation": "dot1q", + "vlan": 10 + }, + "network": { + "encapsulation": "dot1q", + "outer_vlan": 32, + "inner_vlan": 54 + } + } + }, + { + "name": "Ethernet68.3", + "description": "Test_encapsulation_vlan3", + "encapsulation_vlan": { + "client": { + "encapsulation": "dot1ad", + "vlan": 12 + }, + "network": { + "encapsulation": "dot1q", + "vlan": 25 + } + } + }, + { + "name": "Ethernet68.4", + "description": "Test_encapsulation_vlan4", + "encapsulation_vlan": { + "client": { + "encapsulation": "dot1ad", + "outer_vlan": 35, + "inner_vlan": 60, + "inner_encapsulation": "dot1q" + }, + "network": { + "encapsulation": "dot1q", + "outer_vlan": 53, + "inner_vlan": 6, + "inner_encapsulation": "dot1ad" + } + } + }, + { + "name": "Ethernet68.5", + "description": "Test_encapsulation_vlan5", + "encapsulation_vlan": { + "client": { + "encapsulation": "dot1ad", + "outer_vlan": 35, + "inner_vlan": 60 + }, + "network": { + "encapsulation": "dot1ad", + "outer_vlan": 52, + "inner_vlan": 62 + } + } + }, + { + "name": "Ethernet68.6", + "description": "Test_encapsulation_vlan6", + "encapsulation_vlan": { + "client": { + "encapsulation": "dot1ad", + "outer_vlan": 35, + "inner_vlan": 60 + }, + "network": { + "encapsulation": "client" + } + } + }, + { + "name": "Ethernet68.7", + "description": "Test_encapsulation_vlan7", + "encapsulation_vlan": { + "client": { + "encapsulation": "untagged" + }, + "network": { + "encapsulation": "dot1ad", + "outer_vlan": 35, + "inner_vlan": 60 + } + } + }, + { + "name": "Ethernet68.8", + "description": "Test_encapsulation_vlan8", + "encapsulation_vlan": { + "client": { + "encapsulation": "untagged" + }, + "network": { + "encapsulation": "dot1q", + "outer_vlan": 35, + "inner_vlan": 60 + } + } + }, + { + "name": "Ethernet68.9", + "description": "Test_encapsulation_vlan9", + "encapsulation_vlan": { + "client": { + "encapsulation": "untagged" + }, + "network": { + "encapsulation": "untagged" + } + } + }, + { + "name": "Ethernet68.10", + "description": "Test_encapsulation_vlan9", + "encapsulation_vlan": { + "client": { + "encapsulation": "dot1q", + "outer_vlan": 14, + "inner_vlan": 11 + }, + "network": { + "encapsulation": "client inner" + } + } + }, + { + "name": "Ethernet70", + "description": "dot1x_aaa_unresponsive", + "shutdown": false, + "dot1x": { + "aaa": { + "unresponsive": { + "eap_response": "success", + "action": { + "traffic_allow_vlan": 10, + "traffic_allow_access_list": "acl1" + }, + "phone_action": { + "apply_cached_results": true, + "cached_results_timeout": { + "time_duration": 10, + "time_duration_unit": "hours" + }, + "traffic_allow": true, + "apply_alternate": true + } + } + }, + "mac_based_access_list": true + } + }, + { + "name": "Ethernet71", + "description": "dot1x_aaa_unresponsive1", + "shutdown": false, + "dot1x": { + "aaa": { + "unresponsive": { + "eap_response": "success", + "action": { + "traffic_allow_vlan": 10, + "traffic_allow_access_list": "acl1" + }, + "phone_action": { + "apply_cached_results": true, + "cached_results_timeout": { + "time_duration": 10, + "time_duration_unit": "hours" + } + } + } + }, + "mac_based_access_list": true + } + }, + { + "name": "Ethernet72", + "description": "dot1x_aaa_unresponsive2", + "shutdown": false, + "dot1x": { + "aaa": { + "unresponsive": { + "eap_response": "success", + "action": { + "traffic_allow_vlan": 10, + "traffic_allow_access_list": "acl1" + } + } + }, + "mac_based_access_list": true + } + } + ], + "ansible_facts": {}, + "testdir": "eos_cli_config_gen", + "playbook_dir": "/home/holbech/avd/python-avd/scripts", + "ansible_playbook_python": "/usr/bin/python3.10", + "ansible_config_file": null, + "groups": { + "all": [ + "aaa", + "aaa-2", + "acl", + "address-locking", + "aliases", + "agents", + "application-traffic-recognition", + "arp", + "as-path", + "base", + "banners_without_eof", + "boot", + "class-maps", + "clock", + "config-comment", + "cvx", + "cvx-2", + "custom-templates", + "daemon_terminattr", + "daemons", + "dps-interfaces", + "dns-ntp", + "domain-list", + "dhcp-relay", + "dhcp-servers", + "dot1x", + "dot1x-2", + "enable-password", + "eos_cli_config_gen_configuration.enable", + "eos_cli_config_gen_documentation.enable", + "errdisable", + "ethernet-interfaces", + "event-handlers", + "event-monitor", + "flow-tracking", + "flow-tracking-2", + "generate-default-config", + "groups", + "hardware-counter", + "hardware", + "hide-passwords", + "hostname", + "igmp-snooping", + "interface-defaults", + "interface-profiles", + "ip-access-lists", + "ip-dhcp-relay", + "ip-dhcp-snooping", + "ip-community-lists", + "ip-extended-community-lists", + "ip-extended-community-lists-regexp", + "ip-igmp-snooping-enable", + "ip-nat", + "ip-security", + "ip-routing", + "ip-routing-fib", + "ip-radius-source-interface", + "ip-tacacs-source-interface", + "ip-client-source-interfaces", + "ip-virtual-router-mac-address", + "ipv6-access-lists", + "ipv6-dhcp-relay", + "ipv6-neighbors", + "ipv6-static-routes", + "l2-protocol-forwarding", + "lacp", + "link-tracking-groups", + "lldp", + "load-interval", + "local-users", + "logging-match-list", + "logging-minimal", + "logging", + "mcs-client", + "loopbacks-interfaces", + "mac-address-table", + "maintenance", + "management-accounts", + "management-api-http", + "management-cvx", + "management-api-models", + "management-gnmi", + "management-gnmi-new-flags", + "management-gnmi-grpc-tunnel", + "management-console", + "management-defaults", + "management-interfaces", + "management-security", + "management-ssh", + "management-ssh-custom-cipher", + "management-tech-support", + "mac-access-lists", + "mac-security-eth-po-entropy", + "match-lists", + "mlag-configuration", + "monitor-layer1", + "monitor-connectivity", + "monitor-connectivity-2", + "monitor-sessions", + "monitor-session-default-encapsulation-gre", + "monitor-telemetry-influx", + "monitor-telemetry-postcard-policy", + "mpls", + "mpls-2", + "mpls-3", + "none_configuration", + "ntp", + "object-tracking", + "patch-panel", + "peer-filters", + "platform", + "poe", + "policy-maps", + "policy-maps-pbr", + "port-channel-interfaces", + "prefix-lists", + "prompt", + "prompt-2", + "ptp", + "qos", + "queue-monitor-length", + "queue-monitor-length-notifying", + "queue-monitor-streaming", + "radius-server", + "radius-server-2", + "redundancy", + "roles", + "route-maps", + "router-adaptive-virtual-topology", + "router-adaptive-virtual-topology-2", + "router-bfd-1", + "router-bfd-2", + "router-bgp-additional-paths", + "router-bgp-base", + "router-bgp-evpn", + "router-bgp-evpn-vpn-import-pruning", + "router-bgp-evpn-mpls", + "router-bgp-ipv4-labeled-unicast", + "router-bgp-link-state", + "router-bgp-path-selection", + "router-bgp-rtc", + "router-bgp-v4-evpn", + "router-bgp-v4-v6-evpn", + "router-bgp-v4-v6-sr-te", + "router-bgp-vpn-ipv4-vpn-ipv6", + "router-bgp-vpws", + "router-bgp-vrf-address-families", + "router-bgp-vrf-lite", + "router-general", + "router-isis", + "router-isis-new", + "router-isis-1", + "router-isis-2", + "router-l2-vpn", + "router-msdp", + "router-multicast", + "router-ospf", + "router-path-selection", + "router-pim-sparse-mode", + "router-service-insertion", + "router-igmp", + "router-internet-exit", + "service-routing-configuration-bgp", + "service-routing-protocols-model", + "service-routing-protocols-model-2", + "router-traffic-engineering", + "router-segment-security", + "sflow", + "snmp", + "snmp-server-traps", + "spanning-tree", + "spanning-tree-bpdu", + "spanning-tree-rstp", + "spanning-tree-rapid-pvst", + "switchport-mode", + "switchport-port-security", + "stun", + "sync-e", + "tcam-profile", + "static-routes", + "system", + "tap-aggregation", + "terminal", + "terminattr-cloud", + "terminattr-extra-flags", + "terminattr-multi-cluster-certs", + "terminattr-multi-cluster", + "terminattr-onprem-certs", + "terminattr-onprem-token", + "terminattr-prem", + "terminattr-prem-no-ingestkey", + "terminattr-prem-disableaaa", + "traffic-policies", + "traffic-policies-2", + "traffic-policies-3", + "transceiver_qsfp_default_mode_4x10_false", + "tunnel-interfaces", + "unsupported-transceiver", + "vlan-interfaces", + "virtual-source-nat", + "vlan-internal-order", + "vlans", + "vmtracer-sessions", + "vxlan-interface", + "vxlan-interface-false", + "vrf-instances" + ], + "ungrouped": [], + "test_hosts": [ + "aaa", + "aaa-2", + "acl", + "address-locking", + "aliases", + "agents", + "application-traffic-recognition", + "arp", + "as-path", + "base", + "banners_without_eof", + "boot", + "class-maps", + "clock", + "config-comment", + "cvx", + "cvx-2", + "custom-templates", + "daemon_terminattr", + "daemons", + "dps-interfaces", + "dns-ntp", + "domain-list", + "dhcp-relay", + "dhcp-servers", + "dot1x", + "dot1x-2", + "enable-password", + "eos_cli_config_gen_configuration.enable", + "eos_cli_config_gen_documentation.enable", + "errdisable", + "ethernet-interfaces", + "event-handlers", + "event-monitor", + "flow-tracking", + "flow-tracking-2", + "generate-default-config", + "groups", + "hardware-counter", + "hardware", + "hide-passwords", + "hostname", + "igmp-snooping", + "interface-defaults", + "interface-profiles", + "ip-access-lists", + "ip-dhcp-relay", + "ip-dhcp-snooping", + "ip-community-lists", + "ip-extended-community-lists", + "ip-extended-community-lists-regexp", + "ip-igmp-snooping-enable", + "ip-nat", + "ip-security", + "ip-routing", + "ip-routing-fib", + "ip-radius-source-interface", + "ip-tacacs-source-interface", + "ip-client-source-interfaces", + "ip-virtual-router-mac-address", + "ipv6-access-lists", + "ipv6-dhcp-relay", + "ipv6-neighbors", + "ipv6-static-routes", + "l2-protocol-forwarding", + "lacp", + "link-tracking-groups", + "lldp", + "load-interval", + "local-users", + "logging-match-list", + "logging-minimal", + "logging", + "mcs-client", + "loopbacks-interfaces", + "mac-address-table", + "maintenance", + "management-accounts", + "management-api-http", + "management-cvx", + "management-api-models", + "management-gnmi", + "management-gnmi-new-flags", + "management-gnmi-grpc-tunnel", + "management-console", + "management-defaults", + "management-interfaces", + "management-security", + "management-ssh", + "management-ssh-custom-cipher", + "management-tech-support", + "mac-access-lists", + "mac-security-eth-po-entropy", + "match-lists", + "mlag-configuration", + "monitor-layer1", + "monitor-connectivity", + "monitor-connectivity-2", + "monitor-sessions", + "monitor-session-default-encapsulation-gre", + "monitor-telemetry-influx", + "monitor-telemetry-postcard-policy", + "mpls", + "mpls-2", + "mpls-3", + "none_configuration", + "ntp", + "object-tracking", + "patch-panel", + "peer-filters", + "platform", + "poe", + "policy-maps", + "policy-maps-pbr", + "port-channel-interfaces", + "prefix-lists", + "prompt", + "prompt-2", + "ptp", + "qos", + "queue-monitor-length", + "queue-monitor-length-notifying", + "queue-monitor-streaming", + "radius-server", + "radius-server-2", + "redundancy", + "roles", + "route-maps", + "router-adaptive-virtual-topology", + "router-adaptive-virtual-topology-2", + "router-bfd-1", + "router-bfd-2", + "router-bgp-additional-paths", + "router-bgp-base", + "router-bgp-evpn", + "router-bgp-evpn-vpn-import-pruning", + "router-bgp-evpn-mpls", + "router-bgp-ipv4-labeled-unicast", + "router-bgp-link-state", + "router-bgp-path-selection", + "router-bgp-rtc", + "router-bgp-v4-evpn", + "router-bgp-v4-v6-evpn", + "router-bgp-v4-v6-sr-te", + "router-bgp-vpn-ipv4-vpn-ipv6", + "router-bgp-vpws", + "router-bgp-vrf-address-families", + "router-bgp-vrf-lite", + "router-general", + "router-isis", + "router-isis-new", + "router-isis-1", + "router-isis-2", + "router-l2-vpn", + "router-msdp", + "router-multicast", + "router-ospf", + "router-path-selection", + "router-pim-sparse-mode", + "router-service-insertion", + "router-igmp", + "router-internet-exit", + "service-routing-configuration-bgp", + "service-routing-protocols-model", + "service-routing-protocols-model-2", + "router-traffic-engineering", + "router-segment-security", + "sflow", + "snmp", + "snmp-server-traps", + "spanning-tree", + "spanning-tree-bpdu", + "spanning-tree-rstp", + "spanning-tree-rapid-pvst", + "switchport-mode", + "switchport-port-security", + "stun", + "sync-e", + "tcam-profile", + "static-routes", + "system", + "tap-aggregation", + "terminal", + "terminattr-cloud", + "terminattr-extra-flags", + "terminattr-multi-cluster-certs", + "terminattr-multi-cluster", + "terminattr-onprem-certs", + "terminattr-onprem-token", + "terminattr-prem", + "terminattr-prem-no-ingestkey", + "terminattr-prem-disableaaa", + "traffic-policies", + "traffic-policies-2", + "traffic-policies-3", + "transceiver_qsfp_default_mode_4x10_false", + "tunnel-interfaces", + "unsupported-transceiver", + "vlan-interfaces", + "virtual-source-nat", + "vlan-internal-order", + "vlans", + "vmtracer-sessions", + "vxlan-interface", + "vxlan-interface-false", + "vrf-instances" + ] + }, + "ansible_version": { + "string": "2.17.0", + "full": "2.17.0", + "major": 2, + "minor": 17, + "revision": 0 + }, + "ansible_check_mode": false, + "ansible_diff_mode": false, + "ansible_forks": 10, + "ansible_inventory_sources": [ + "/home/holbech/avd/ansible_collections/arista/avd/molecule/eos_cli_config_gen/inventory/hosts.ini" + ], + "ansible_skip_tags": [], + "ansible_limit": "all:!prompt:!custom-templates", + "ansible_run_tags": [ + "all" + ], + "ansible_verbosity": 0 +} \ No newline at end of file diff --git a/python-avd/tests/schema_tools/generate_classes/artifacts/.gitignore b/python-avd/tests/schema_tools/generate_classes/artifacts/.gitignore new file mode 100644 index 00000000000..9795b59d796 --- /dev/null +++ b/python-avd/tests/schema_tools/generate_classes/artifacts/.gitignore @@ -0,0 +1,5 @@ +* +!.gitignore +!__init__.py +!types.py +!models.py diff --git a/python-avd/tests/schema_tools/generate_classes/artifacts/__init__.py b/python-avd/tests/schema_tools/generate_classes/artifacts/__init__.py new file mode 100644 index 00000000000..e772bee41fe --- /dev/null +++ b/python-avd/tests/schema_tools/generate_classes/artifacts/__init__.py @@ -0,0 +1,3 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. diff --git a/python-avd/tests/schema_tools/generate_classes/test_class_src_gen.py b/python-avd/tests/schema_tools/generate_classes/test_class_src_gen.py new file mode 100644 index 00000000000..5a56e182f75 --- /dev/null +++ b/python-avd/tests/schema_tools/generate_classes/test_class_src_gen.py @@ -0,0 +1,70 @@ +# Copyright (c) 2023-2024 Arista Networks, Inc. +# Use of this source code is governed by the Apache License 2.0 +# that can be found in the LICENSE file. +import json +import sys +from importlib import import_module +from pathlib import Path + +import pytest + +# Override global path to load schema from source instead of any installed version. +sys.path.insert(0, str(Path(__file__).parents[3])) + +import pyavd._schema.models.avd_model +from schema_tools.generate_classes.src_generators import FileSrc +from schema_tools.generate_classes.utils import generate_class_name +from schema_tools.metaschema.meta_schema_model import AristaAvdSchema +from schema_tools.store import create_store + +TEST_DATA = [ + # (schema_name: str, data_file: str | none) + ("eos_cli_config_gen", None), + ("eos_designs", None), + ("eos_cli_config_gen", "ethernet-interfaces.json"), + ("eos_designs", "DC1-BL1A.json"), +] + +TEST_SCHEMAS_FROM_STORE = ["eos_cli_config_gen", "eos_designs"] + + +def load_data_file(data_file: Path) -> dict: + with data_file.open(encoding="UTF-8") as file: + return json.load(file) + + +# Loading from YAML to get the schema with $refs in it instead of the fully resolved schema stored in the .pickle files. +STORE = create_store(load_from_yaml=True) + +sys.path.insert(0, str(Path(__file__).parent)) + + +@pytest.mark.parametrize("schema_name", TEST_SCHEMAS_FROM_STORE) +def test_generate_class_src(schema_name: str) -> None: + """ + Builds Python classes from the schemas in the schema store. + + Writes the resulting models to python files under artifacts/. + """ + schema = AristaAvdSchema(_resolve_schema=schema_name, **STORE[schema_name]) + output_file = Path(__file__).parent.joinpath(f"artifacts/{schema_name}.py") + schemasrc = schema._generate_class_src(class_name=generate_class_name(schema_name)) + src_file_contents = FileSrc(classes=[schemasrc.cls]) + with output_file.open(mode="w", encoding="UTF-8") as file: + file.write(str(src_file_contents)) + + +@pytest.mark.parametrize(("schema_name", "data_file"), TEST_DATA) +def test_import_and_load_model(schema_name: str, data_file: str | None, artifacts_path: Path) -> None: + """Imports the generated Python classes and initializes them with data from the given data_file or no data.""" + module = import_module(f"artifacts.{schema_name}") + class_name = generate_class_name(schema_name) + cls = getattr(module, class_name) + assert issubclass(cls, pyavd._schema.models.avd_model.AvdModel) + + data = {} if data_file is None else load_data_file(artifacts_path.joinpath(data_file)) + + # Initialize the loaded class with data. + model = cls._from_dict(data) + + assert isinstance(model, pyavd._schema.models.avd_model.AvdModel) diff --git a/python-avd/tests/schema_tools/generate_docs/test_mdtabsgen.py b/python-avd/tests/schema_tools/generate_docs/test_mdtabsgen.py index ba5ede5eb4b..bc75457eb5f 100644 --- a/python-avd/tests/schema_tools/generate_docs/test_mdtabsgen.py +++ b/python-avd/tests/schema_tools/generate_docs/test_mdtabsgen.py @@ -3,6 +3,7 @@ # that can be found in the LICENSE file. from pathlib import Path from sys import path +from typing import Any from unittest.mock import patch import pytest @@ -13,6 +14,7 @@ from schema_tools.generate_docs.mdtabsgen import get_md_tabs from schema_tools.metaschema.meta_schema_model import AristaAvdSchema +from schema_tools.metaschema.resolvemodel import get_schema_from_ref @pytest.mark.parametrize("table_name", ["network-services-multicast-settings"]) @@ -28,13 +30,19 @@ def test_get_md_tabs(table_name: str, schema_store: dict, artifacts_path: Path, output_file = output_path.joinpath(f"{table_name}.md") expected_file = artifacts_path.joinpath(f"expected-{table_name}.md") - def mocked_create_store() -> dict: + def mocked_create_store(*_args: Any, **_kwargs: Any) -> dict: return schema_store with patch("schema_tools.metaschema.resolvemodel.create_store", new=mocked_create_store): - schema = AristaAvdSchema(resolve_schema=True, **raw_schema) + # Reset lru_cache in the resolver code to force it to read the schemas from our mocked store. + get_schema_from_ref.cache_clear() + + schema = AristaAvdSchema(**raw_schema) md_tabs = get_md_tabs(schema, table_name) + # Reset lru_cache in the resolver code to force it to read the schemas next time instead of taking them from our mocked store. + get_schema_from_ref.cache_clear() + with Path(output_file).open(mode="w", encoding="UTF-8") as file: file.write(md_tabs) with Path(expected_file).open(encoding="UTF-8") as file: diff --git a/python-avd/tests/schema_tools/metaschema/test_meta_schema_model.py b/python-avd/tests/schema_tools/metaschema/test_meta_schema_model.py index 9d74b868a63..4879ac11dd0 100644 --- a/python-avd/tests/schema_tools/metaschema/test_meta_schema_model.py +++ b/python-avd/tests/schema_tools/metaschema/test_meta_schema_model.py @@ -31,7 +31,7 @@ def test_pydantic_dump_matches_original_yaml() -> None: Then compares the input schema with the dumped schema. """ - pydantic_schema = AristaAvdSchema(resolve_schema=False, **raw_schema) + pydantic_schema = AristaAvdSchema(_resolve_schema=False, **raw_schema) dump_raw_schema = yaml.dump(raw_schema, Dumper=NoAliasDumper) dump_pydantic_schema = yaml.dump(json.loads(pydantic_schema.model_dump_json(by_alias=True, exclude_unset=True)), Dumper=NoAliasDumper) diff --git a/python-avd/tests/utils.py b/python-avd/tests/utils.py index ff768263bd7..b0e3e72f009 100644 --- a/python-avd/tests/utils.py +++ b/python-avd/tests/utils.py @@ -6,7 +6,8 @@ from pathlib import Path from sys import stdin -from yaml import unsafe_load as yaml_load +from yaml import CSafeLoader +from yaml import load as yaml_load def read_file(filename: str) -> str: @@ -24,7 +25,7 @@ def read_vars(filename: str) -> dict: except JSONDecodeError: pass - return yaml_load(data) or {} + return yaml_load(data, Loader=CSafeLoader) or {} def write_result(filename: str, result: str) -> None: diff --git a/python-avd/tox.ini b/python-avd/tox.ini index 768f410200f..b9d3f780815 100644 --- a/python-avd/tox.ini +++ b/python-avd/tox.ini @@ -17,7 +17,6 @@ python = 3.13: py313 [testenv] -description = run the tests with our own runner package = wheel wheel_build_env = .pkg dependency_groups =